accelerator.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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)) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/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 { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (platform_accelerator_.get() != rhs.platform_accelerator_.get() && 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ((!platform_accelerator_.get() || !rhs.platform_accelerator_.get()) || 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !platform_accelerator_->Equals(*rhs.platform_accelerator_))) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (key_code_ == rhs.key_code_) && (type_ == rhs.type_) && 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (modifiers_ == rhs.modifiers_); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::operator !=(const Accelerator& rhs) const { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(*this == rhs); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsShiftDown() const { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_SHIFT_DOWN) != 0; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCtrlDown() const { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_CONTROL_DOWN) != 0; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsAltDown() const { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_ALT_DOWN) != 0; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Accelerator::IsCmdDown() const { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (modifiers_ & EF_COMMAND_DOWN) != 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 Accelerator::GetShortcutText() const { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_id = 0; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch(key_code_) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_TAB: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_TAB_KEY; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_RETURN: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_ENTER_KEY; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_ESCAPE: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_ESC_KEY; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_PRIOR: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_PAGEUP_KEY; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_NEXT: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_PAGEDOWN_KEY; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_END: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_END_KEY; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_HOME: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_HOME_KEY; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_INSERT: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_INSERT_KEY; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_DELETE: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_DELETE_KEY; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_LEFT: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_LEFT_ARROW_KEY; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_RIGHT: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_RIGHT_ARROW_KEY; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_BACK: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_BACKSPACE_KEY; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_F1: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_F1_KEY; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_F11: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_id = IDS_APP_F11_KEY; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 shortcut; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!string_id) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our fallback is to try translate the key code to a regular character 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unless it is one of digits (VK_0 to VK_9). Some keyboard 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layouts have characters other than digits assigned in 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an unshifted mode (e.g. French AZERY layout has 'a with grave 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // accent' for '0'). For display in the menu (e.g. Ctrl-0 for the 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default zoom level), we leave VK_[0-9] alone without translation. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t key; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_code_ >= '0' && key_code_ <= '9') 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = key_code_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = LOWORD(::MapVirtualKeyW(key_code_, MAPVK_VK_TO_CHAR)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut += key; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_AURA) || defined(OS_MACOSX) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint16 c = GetCharacterFromKeyCode(key_code_, false); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c != 0) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut += static_cast<string16::value_type>(base::ToUpperASCII(c)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(TOOLKIT_GTK) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gchar* name = NULL; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (key_code_) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_OEM_2: 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = static_cast<const gchar*>("/"); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = gdk_keyval_name(gdk_keyval_to_lower(key_code_)); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name[0] != 0 && name[1] == 0) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut += static_cast<string16::value_type>(g_ascii_toupper(name[0])); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut += UTF8ToUTF16(name); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringUTF16(string_id); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checking whether the character used for the accelerator is alphanumeric. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it is not, then we need to adjust the string later on if the locale is 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right-to-left. See below for more information of why such adjustment is 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // required. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 shortcut_rtl; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool adjust_shortcut_for_rtl = false; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL() && shortcut.length() == 1 && 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsAsciiAlpha(shortcut[0]) && !IsAsciiDigit(shortcut[0])) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adjust_shortcut_for_rtl = true; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_rtl.assign(shortcut); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsShiftDown()) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_SHIFT_MODIFIER, shortcut); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we use 'else-if' in order to avoid using Ctrl+Alt as a shortcut. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://blogs.msdn.com/oldnewthing/archive/2004/03/29/101121.aspx for 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more information. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCtrlDown()) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_CONTROL_MODIFIER, shortcut); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (IsAltDown()) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_ALT_MODIFIER, shortcut); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCmdDown()) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut = l10n_util::GetStringFUTF16(IDS_APP_COMMAND_MODIFIER, shortcut); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For some reason, menus in Windows ignore standard Unicode directionality 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // marks (such as LRE, PDF, etc.). On RTL locales, we use RTL menus and 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // therefore any text we draw for the menu items is drawn in an RTL context. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thus, the text "Ctrl++" (which we currently use for the Zoom In option) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears as "++Ctrl" in RTL because the Unicode BiDi algorithm puts 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // punctuations on the left when the context is right-to-left. Shortcuts that 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do not end with a punctuation mark (such as "Ctrl+H" do not have this 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // problem). 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The only way to solve this problem is to adjust the string if the locale 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is RTL so that it is drawn correctly in an RTL context. Instead of 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returning "Ctrl++" in the above example, we return "++Ctrl". This will 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause the text to appear as "Ctrl++" when Windows draws the string in an 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RTL context because the punctuation no longer appears at the end of the 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(idana) bug# 1232732: this hack can be avoided if instead of using 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::Menu we use views::MenuItemView because the latter is a View 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subclass and therefore it supports marking text as RTL or LTR using 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // standard Unicode directionality marks. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust_shortcut_for_rtl) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_length = static_cast<int>(shortcut_rtl.length()); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(key_length, 0); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_rtl.append(ASCIIToUTF16("+")); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subtracting the size of the shortcut key and 1 for the '+' sign. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_rtl.append(shortcut, 0, shortcut.length() - key_length - 1); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut.swap(shortcut_rtl); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shortcut; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 250