12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/keycode_text_conversion.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/keysym.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/XKBlib.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/Xlib.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/Xutil.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/x/x11_util.h"
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion_x.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct KeyCodeAndXKeyCode {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::KeyboardCode key_code;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x_key_code;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Contains a list of keyboard codes, in order, with their corresponding
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// X key code. This list is not complete.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(kkania): Merge this table with the existing one in
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// keyboard_code_conversion_x.cc.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeyCodeAndXKeyCode kKeyCodeToXKeyCode[] = {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_BACK, 22 },
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_TAB, 23 },
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_RETURN, 36 },
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_SHIFT, 50 },
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_CONTROL, 37 },
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_MENU, 64 },
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_CAPITAL, 66 },
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_HANGUL, 130 },
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_HANJA, 131 },
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_ESCAPE, 9 },
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_SPACE, 65 },
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_PRIOR, 112 },
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NEXT, 117 },
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_END, 115 },
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_HOME, 110 },
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_LEFT, 113 },
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_UP, 111 },
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_RIGHT, 114 },
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_DOWN, 116 },
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_INSERT, 118 },
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_DELETE, 119 },
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_0, 19 },
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_1, 10 },
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_2, 11 },
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_3, 12 },
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_4, 13 },
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_5, 14 },
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_6, 15 },
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_7, 16 },
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_8, 17 },
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_9, 18 },
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_A, 38 },
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_B, 56 },
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_C, 54 },
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_D, 40 },
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_E, 26 },
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F, 41 },
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_G, 42 },
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_H, 43 },
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_I, 31 },
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_J, 44 },
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_K, 45 },
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_L, 46 },
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_M, 58 },
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_N, 57 },
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_O, 32 },
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_P, 33 },
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_Q, 24 },
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_R, 27 },
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_S, 39 },
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_T, 28 },
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_U, 30 },
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_V, 55 },
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_W, 25 },
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_X, 53 },
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_Y, 29 },
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_Z, 52 },
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_LWIN, 133 },
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD0, 90 },
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD1, 87 },
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD2, 88 },
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD3, 89 },
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD4, 83 },
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD5, 84 },
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD6, 85 },
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD7, 79 },
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD8, 80 },
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMPAD9, 81 },
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_MULTIPLY, 63 },
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_ADD, 86 },
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_SUBTRACT, 82 },
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_DECIMAL, 129 },
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_DIVIDE, 106 },
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F1, 67 },
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F2, 68 },
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F3, 69 },
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F4, 70 },
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F5, 71 },
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F6, 72 },
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F7, 73 },
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F8, 74 },
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F9, 75 },
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F10, 76 },
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F11, 95 },
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_F12, 96 },
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_NUMLOCK, 77 },
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_SCROLL, 78 },
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_1, 47 },
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_PLUS, 21 },
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_COMMA, 59 },
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_MINUS, 20 },
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_PERIOD, 60 },
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_2, 61 },
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_3, 49 },
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_4, 34 },
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_5, 51 },
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_6, 35 },
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { ui::VKEY_OEM_7, 48 }
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Uses to compare two KeyCodeAndXKeyCode structs based on their key code.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool operator<(const KeyCodeAndXKeyCode& a, const KeyCodeAndXKeyCode& b) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return a.key_code < b.key_code;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the equivalent X key code for the given key code. Returns -1 if
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// no X equivalent was found.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KeyboardCodeToXKeyCode(ui::KeyboardCode key_code) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KeyCodeAndXKeyCode find;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  find.key_code = key_code;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KeyCodeAndXKeyCode* found = std::lower_bound(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kKeyCodeToXKeyCode, kKeyCodeToXKeyCode + arraysize(kKeyCodeToXKeyCode),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      find);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (found >= kKeyCodeToXKeyCode + arraysize(kKeyCodeToXKeyCode) ||
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      found->key_code != key_code)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return found->x_key_code;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets the X modifier mask (Mod1Mask through Mod5Mask) for the given
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// modifier. Only checks the alt, meta, and num lock keys currently.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true on success.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetXModifierMask(Display* display, int modifier, int* x_modifier) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XModifierKeymap* mod_map = XGetModifierMapping(display);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool found = false;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int max_mod_keys = mod_map->max_keypermod;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int mod_index = 0; mod_index <= 8; ++mod_index) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int key_index = 0; key_index < max_mod_keys; ++key_index) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int key = mod_map->modifiermap[mod_index * max_mod_keys + key_index];
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int keysym = XkbKeycodeToKeysym(display, key, 0, 0);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (modifier == kAltKeyModifierMask)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        found = keysym == XK_Alt_L || keysym == XK_Alt_R;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (modifier == kMetaKeyModifierMask)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        found = keysym == XK_Meta_L || keysym == XK_Meta_R;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (modifier == kNumLockKeyModifierMask)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        found = keysym == XK_Num_Lock;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (found) {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *x_modifier = 1 << mod_index;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (found)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XFreeModifiermap(mod_map);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return found;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1805e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)bool ConvertKeyCodeToText(
1815e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    ui::KeyboardCode key_code, int modifiers, std::string* text,
1825e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    std::string* error_msg) {
1835e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  *error_msg = std::string();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x_key_code = KeyboardCodeToXKeyCode(key_code);
1855e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (x_key_code == -1) {
1865e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    *text = std::string();
1875e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    return true;
1885e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XEvent event;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(&event, 0, sizeof(XEvent));
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XKeyEvent* key_event = &event.xkey;
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XDisplay* display = gfx::GetXDisplay();
1945e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (!display) {
1955e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    *error_msg =
1965e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        "an X display is required for keycode conversions, consider using Xvfb";
1975e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    *text = std::string();
1985e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    return false;
1995e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key_event->display = display;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key_event->keycode = x_key_code;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifiers & kShiftKeyModifierMask)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_event->state |= ShiftMask;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifiers & kControlKeyModifierMask)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_event->state |= ControlMask;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make a best attempt for non-standard modifiers.
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x_modifier;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifiers & kAltKeyModifierMask &&
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetXModifierMask(display, kAltKeyModifierMask, &x_modifier)) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_event->state |= x_modifier;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifiers & kMetaKeyModifierMask &&
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetXModifierMask(display, kMetaKeyModifierMask, &x_modifier)) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_event->state |= x_modifier;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifiers & kNumLockKeyModifierMask &&
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetXModifierMask(display, kNumLockKeyModifierMask, &x_modifier)) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_event->state |= x_modifier;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key_event->type = KeyPress;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint16 character = ui::GetCharacterFromXEvent(&event);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!character)
2255e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    *text = std::string();
2265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  else
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *text = base::UTF16ToUTF8(base::string16(1, character));
2285e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return true;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ConvertCharToKeyCode(
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::char16 key,
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::KeyboardCode* key_code,
2345e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    int* necessary_modifiers,
2355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    std::string* error_msg) {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string key_string(base::UTF16ToUTF8(base::string16(1, key)));
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool found = false;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::KeyboardCode test_code;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int test_modifiers;
2405e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  *error_msg = std::string();
2415e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  std::string conv_string;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kKeyCodeToXKeyCode); ++i) {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_code = kKeyCodeToXKeyCode[i].key_code;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Skip the numpad keys.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (test_code >= ui::VKEY_NUMPAD0 && test_code <= ui::VKEY_DIVIDE)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_modifiers = 0;
2485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    if (!ConvertKeyCodeToText(
2495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        test_code, test_modifiers, &conv_string, error_msg))
2505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      return false;
2515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    if (conv_string == key_string) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      found = true;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_modifiers = kShiftKeyModifierMask;
2565e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    if (!ConvertKeyCodeToText(
2575e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        test_code, test_modifiers, &conv_string, error_msg))
2585e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      return false;
2595e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    if (conv_string == key_string) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      found = true;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (found) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *key_code = test_code;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *necessary_modifiers = test_modifiers;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return found;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
270