accelerator.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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)#endif 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_MACOSX)) 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::Accelerator() 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : key_code_(ui::VKEY_UNKNOWN), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(ui::ET_KEY_PRESSED), 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) modifiers_(0), 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) is_repeat_(false) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::Accelerator(KeyboardCode keycode, int modifiers) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : key_code_(keycode), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(ui::ET_KEY_PRESSED), 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) modifiers_(modifiers), 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) is_repeat_(false) { 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_; 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) is_repeat_ = accelerator.is_repeat_; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (accelerator.platform_accelerator_.get()) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator::~Accelerator() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Accelerator& Accelerator::operator=(const Accelerator& accelerator) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this != &accelerator) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_code_ = accelerator.key_code_; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_ = accelerator.type_; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers_ = accelerator.modifiers_; 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) is_repeat_ = accelerator.is_repeat_; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (accelerator.platform_accelerator_.get()) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy(); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) platform_accelerator_.reset(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator <(const Accelerator& rhs) const { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_code_ != rhs.key_code_) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key_code_ < rhs.key_code_; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_ != rhs.type_) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_ < rhs.type_; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return modifiers_ < rhs.modifiers_; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator ==(const Accelerator& rhs) const { 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((key_code_ == rhs.key_code_) && (type_ == rhs.type_) && 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (modifiers_ == rhs.modifiers_)) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool platform_equal = 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) platform_accelerator_.get() && rhs.platform_accelerator_.get() && 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) platform_accelerator_.get() == rhs.platform_accelerator_.get(); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return platform_equal; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator !=(const Accelerator& rhs) const { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(*this == rhs); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsShiftDown() const { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_SHIFT_DOWN) != 0; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCtrlDown() const { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_CONTROL_DOWN) != 0; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsAltDown() const { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_ALT_DOWN) != 0; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCmdDown() const { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_COMMAND_DOWN) != 0; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool Accelerator::IsRepeat() const { 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return is_repeat_; 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::string16 Accelerator::GetShortcutText() const { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_id = 0; 110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (key_code_) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_TAB: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_TAB_KEY; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_RETURN: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_ENTER_KEY; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_ESCAPE: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_ESC_KEY; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_PRIOR: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_PAGEUP_KEY; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_NEXT: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_PAGEDOWN_KEY; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_END: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_END_KEY; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_HOME: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_HOME_KEY; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_INSERT: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_INSERT_KEY; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_DELETE: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_DELETE_KEY; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_LEFT: 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_LEFT_ARROW_KEY; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_RIGHT: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_RIGHT_ARROW_KEY; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_UP: 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) string_id = IDS_APP_UP_ARROW_KEY; 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_DOWN: 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) string_id = IDS_APP_DOWN_ARROW_KEY; 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_BACK: 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_BACKSPACE_KEY; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_F1: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_F1_KEY; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_F11: 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_F11_KEY; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_OEM_COMMA: 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) string_id = IDS_APP_COMMA_KEY; 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_OEM_PERIOD: 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) string_id = IDS_APP_PERIOD_KEY; 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ui::VKEY_MEDIA_NEXT_TRACK: 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) string_id = IDS_APP_MEDIA_NEXT_TRACK_KEY; 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ui::VKEY_MEDIA_PLAY_PAUSE: 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) string_id = IDS_APP_MEDIA_PLAY_PAUSE_KEY; 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ui::VKEY_MEDIA_PREV_TRACK: 17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) string_id = IDS_APP_MEDIA_PREV_TRACK_KEY; 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ui::VKEY_MEDIA_STOP: 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) string_id = IDS_APP_MEDIA_STOP_KEY; 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::string16 shortcut; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!string_id) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our fallback is to try translate the key code to a regular character 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unless it is one of digits (VK_0 to VK_9). Some keyboard 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layouts have characters other than digits assigned in 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an unshifted mode (e.g. French AZERY layout has 'a with grave 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // accent' for '0'). For display in the menu (e.g. Ctrl-0 for the 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default zoom level), we leave VK_[0-9] alone without translation. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t key; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_code_ >= '0' && key_code_ <= '9') 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = key_code_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = LOWORD(::MapVirtualKeyW(key_code_, MAPVK_VK_TO_CHAR)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut += key; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_AURA) || defined(OS_MACOSX) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint16 c = GetCharacterFromKeyCode(key_code_, false); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c != 0) 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) shortcut += 200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) static_cast<base::string16::value_type>(base::ToUpperASCII(c)); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringUTF16(string_id); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checking whether the character used for the accelerator is alphanumeric. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it is not, then we need to adjust the string later on if the locale is 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right-to-left. See below for more information of why such adjustment is 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // required. 210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::string16 shortcut_rtl; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool adjust_shortcut_for_rtl = false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL() && shortcut.length() == 1 && 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsAsciiAlpha(shortcut[0]) && !IsAsciiDigit(shortcut[0])) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adjust_shortcut_for_rtl = true; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_rtl.assign(shortcut); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsShiftDown()) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_SHIFT_MODIFIER, shortcut); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we use 'else-if' in order to avoid using Ctrl+Alt as a shortcut. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://blogs.msdn.com/oldnewthing/archive/2004/03/29/101121.aspx for 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more information. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCtrlDown()) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_CONTROL_MODIFIER, shortcut); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (IsAltDown()) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_ALT_MODIFIER, shortcut); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCmdDown()) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_COMMAND_MODIFIER, shortcut); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For some reason, menus in Windows ignore standard Unicode directionality 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // marks (such as LRE, PDF, etc.). On RTL locales, we use RTL menus and 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // therefore any text we draw for the menu items is drawn in an RTL context. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thus, the text "Ctrl++" (which we currently use for the Zoom In option) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears as "++Ctrl" in RTL because the Unicode BiDi algorithm puts 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // punctuations on the left when the context is right-to-left. Shortcuts that 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do not end with a punctuation mark (such as "Ctrl+H" do not have this 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // problem). 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The only way to solve this problem is to adjust the string if the locale 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is RTL so that it is drawn correctly in an RTL context. Instead of 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returning "Ctrl++" in the above example, we return "++Ctrl". This will 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause the text to appear as "Ctrl++" when Windows draws the string in an 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RTL context because the punctuation no longer appears at the end of the 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(idana) bug# 1232732: this hack can be avoided if instead of using 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::Menu we use views::MenuItemView because the latter is a View 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subclass and therefore it supports marking text as RTL or LTR using 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // standard Unicode directionality marks. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust_shortcut_for_rtl) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_length = static_cast<int>(shortcut_rtl.length()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(key_length, 0); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) shortcut_rtl.append(base::ASCIIToUTF16("+")); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subtracting the size of the shortcut key and 1 for the '+' sign. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_rtl.append(shortcut, 0, shortcut.length() - key_length - 1); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut.swap(shortcut_rtl); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shortcut; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 266