accelerator.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/accelerators/accelerator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(TOOLKIT_GTK)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdk.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_MACOSX))
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::Accelerator()
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : key_code_(ui::VKEY_UNKNOWN),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type_(ui::ET_KEY_PRESSED),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modifiers_(0) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::Accelerator(KeyboardCode keycode, int modifiers)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : key_code_(keycode),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type_(ui::ET_KEY_PRESSED),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modifiers_(modifiers) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::Accelerator(const Accelerator& accelerator) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_code_ = accelerator.key_code_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = accelerator.type_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modifiers_ = accelerator.modifiers_;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (accelerator.platform_accelerator_.get())
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::~Accelerator() {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator& Accelerator::operator=(const Accelerator& accelerator) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this != &accelerator) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key_code_ = accelerator.key_code_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type_ = accelerator.type_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifiers_ = accelerator.modifiers_;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (accelerator.platform_accelerator_.get())
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      platform_accelerator_.reset();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator <(const Accelerator& rhs) const {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key_code_ != rhs.key_code_)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return key_code_ < rhs.key_code_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type_ != rhs.type_)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type_ < rhs.type_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modifiers_ < rhs.modifiers_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator ==(const Accelerator& rhs) const {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if ((key_code_ == rhs.key_code_) && (type_ == rhs.type_) &&
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (modifiers_ == rhs.modifiers_))
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool platform_equal =
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      platform_accelerator_.get() && rhs.platform_accelerator_.get() &&
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      platform_accelerator_.get() == rhs.platform_accelerator_.get();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return platform_equal;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator !=(const Accelerator& rhs) const {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !(*this == rhs);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsShiftDown() const {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (modifiers_ & EF_SHIFT_DOWN) != 0;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCtrlDown() const {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (modifiers_ & EF_CONTROL_DOWN) != 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsAltDown() const {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (modifiers_ & EF_ALT_DOWN) != 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCmdDown() const {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (modifiers_ & EF_COMMAND_DOWN) != 0;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::string16 Accelerator::GetShortcutText() const {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int string_id = 0;
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  switch (key_code_) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_TAB:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_TAB_KEY;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_RETURN:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_ENTER_KEY;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_ESCAPE:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_ESC_KEY;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_PRIOR:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_PAGEUP_KEY;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_NEXT:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_PAGEDOWN_KEY;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_END:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_END_KEY;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_HOME:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_HOME_KEY;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_INSERT:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_INSERT_KEY;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_DELETE:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_DELETE_KEY;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_LEFT:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_LEFT_ARROW_KEY;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_RIGHT:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_RIGHT_ARROW_KEY;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case ui::VKEY_UP:
139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      string_id = IDS_APP_UP_ARROW_KEY;
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      break;
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case ui::VKEY_DOWN:
142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      string_id = IDS_APP_DOWN_ARROW_KEY;
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      break;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_BACK:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_BACKSPACE_KEY;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_F1:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_F1_KEY;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_F11:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_id = IDS_APP_F11_KEY;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case ui::VKEY_OEM_COMMA:
154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      string_id = IDS_APP_COMMA_KEY;
155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      break;
156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case ui::VKEY_OEM_PERIOD:
157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      string_id = IDS_APP_PERIOD_KEY;
158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      break;
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ui::VKEY_MEDIA_NEXT_TRACK:
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      string_id = IDS_APP_MEDIA_NEXT_TRACK_KEY;
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ui::VKEY_MEDIA_PLAY_PAUSE:
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      string_id = IDS_APP_MEDIA_PLAY_PAUSE_KEY;
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ui::VKEY_MEDIA_PREV_TRACK:
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      string_id = IDS_APP_MEDIA_PREV_TRACK_KEY;
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ui::VKEY_MEDIA_STOP:
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      string_id = IDS_APP_MEDIA_STOP_KEY;
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::string16 shortcut;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!string_id) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Our fallback is to try translate the key code to a regular character
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // unless it is one of digits (VK_0 to VK_9). Some keyboard
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // layouts have characters other than digits assigned in
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // an unshifted mode (e.g. French AZERY layout has 'a with grave
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // accent' for '0'). For display in the menu (e.g. Ctrl-0 for the
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // default zoom level), we leave VK_[0-9] alone without translation.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t key;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key_code_ >= '0' && key_code_ <= '9')
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key = key_code_;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key = LOWORD(::MapVirtualKeyW(key_code_, MAPVK_VK_TO_CHAR));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut += key;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_AURA) || defined(OS_MACOSX)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint16 c = GetCharacterFromKeyCode(key_code_, false);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (c != 0)
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      shortcut +=
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          static_cast<base::string16::value_type>(base::ToUpperASCII(c));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(TOOLKIT_GTK)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gchar* name = NULL;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (key_code_) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_OEM_2:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = static_cast<const gchar*>("/");
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = gdk_keyval_name(gdk_keyval_to_lower(key_code_));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (name[0] != 0 && name[1] == 0)
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        shortcut +=
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            static_cast<base::string16::value_type>(g_ascii_toupper(name[0]));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        shortcut += base::UTF8ToUTF16(name);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut = l10n_util::GetStringUTF16(string_id);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checking whether the character used for the accelerator is alphanumeric.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it is not, then we need to adjust the string later on if the locale is
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // right-to-left. See below for more information of why such adjustment is
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // required.
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::string16 shortcut_rtl;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool adjust_shortcut_for_rtl = false;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::i18n::IsRTL() && shortcut.length() == 1 &&
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !IsAsciiAlpha(shortcut[0]) && !IsAsciiDigit(shortcut[0])) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adjust_shortcut_for_rtl = true;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut_rtl.assign(shortcut);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsShiftDown())
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut = l10n_util::GetStringFUTF16(IDS_APP_SHIFT_MODIFIER, shortcut);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we use 'else-if' in order to avoid using Ctrl+Alt as a shortcut.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://blogs.msdn.com/oldnewthing/archive/2004/03/29/101121.aspx for
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // more information.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCtrlDown())
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut = l10n_util::GetStringFUTF16(IDS_APP_CONTROL_MODIFIER, shortcut);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (IsAltDown())
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut = l10n_util::GetStringFUTF16(IDS_APP_ALT_MODIFIER, shortcut);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCmdDown())
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut = l10n_util::GetStringFUTF16(IDS_APP_COMMAND_MODIFIER, shortcut);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For some reason, menus in Windows ignore standard Unicode directionality
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // marks (such as LRE, PDF, etc.). On RTL locales, we use RTL menus and
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // therefore any text we draw for the menu items is drawn in an RTL context.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Thus, the text "Ctrl++" (which we currently use for the Zoom In option)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // appears as "++Ctrl" in RTL because the Unicode BiDi algorithm puts
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // punctuations on the left when the context is right-to-left. Shortcuts that
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // do not end with a punctuation mark (such as "Ctrl+H" do not have this
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // problem).
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The only way to solve this problem is to adjust the string if the locale
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is RTL so that it is drawn correctly in an RTL context. Instead of
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returning "Ctrl++" in the above example, we return "++Ctrl". This will
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cause the text to appear as "Ctrl++" when Windows draws the string in an
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL context because the punctuation no longer appears at the end of the
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(idana) bug# 1232732: this hack can be avoided if instead of using
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::Menu we use views::MenuItemView because the latter is a View
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subclass and therefore it supports marking text as RTL or LTR using
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // standard Unicode directionality marks.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (adjust_shortcut_for_rtl) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int key_length = static_cast<int>(shortcut_rtl.length());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GT(key_length, 0);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    shortcut_rtl.append(base::ASCIIToUTF16("+"));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subtracting the size of the shortcut key and 1 for the '+' sign.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut_rtl.append(shortcut, 0, shortcut.length() - key_length - 1);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shortcut.swap(shortcut_rtl);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shortcut;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
277