Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: chrome/browser/chromeos/input_method/input_method_manager.cc

Issue 7865019: Handle XK_Zenkaku_Hankaku, Henkan, Muhenkan, Hangul etc. in Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/input_method/input_method_manager.h" 5 #include "chrome/browser/chromeos/input_method/input_method_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include <glib.h> 9 #include <glib.h>
10 10
(...skipping 24 matching lines...) Expand all
35 #endif 35 #endif
36 36
37 #include <X11/X.h> // ShiftMask, ControlMask, etc. 37 #include <X11/X.h> // ShiftMask, ControlMask, etc.
38 #include <X11/Xutil.h> // for XK_* macros. 38 #include <X11/Xutil.h> // for XK_* macros.
39 39
40 namespace { 40 namespace {
41 41
42 const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; 42 const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon";
43 43
44 // For hotkey handling. 44 // For hotkey handling.
45 enum HotkeyEvents { 45 enum HotkeyEvent {
46 kPreviousInputMethod = 0, 46 kPreviousInputMethod = 0,
47 kNextInputMethod, 47 kNextInputMethod,
48 kJapaneseInputMethod,
49 kJapaneseLayout,
50 kJapaneseInputMethodOrLayout,
51 kKoreanInputMethodOrLayout,
52 };
53
54 // Engine specific hotkeys.
55 const struct EngineSpecificHotkeySetting {
56 const char* input_method_ids[2];
57 int event_id;
58 KeySym keysym;
59 uint32 modifiers;
60 bool trigger_on_press;
mazda 2011/09/12 10:02:54 What happens if trigger_on_press is false?
Yusuke Sato 2011/09/12 11:46:05 IME or layout is changed on key release. The Shift
mazda 2011/09/12 11:57:31 Thanks. Probably it's better to add comment since
Yusuke Sato 2011/09/12 12:02:14 Done.
61 } kEngineSpecificHotkeySettings[] = {
62 {
63 { "mozc-jp" },
64 kJapaneseInputMethod,
65 XK_Henkan,
66 0x0,
67 true,
68 },
69 {
70 { "xkb:jp::jpn" },
71 kJapaneseLayout,
72 XK_Muhenkan,
73 0x0,
74 true,
75 },
76 {
77 { "mozc-jp", "xkb:jp::jpn" },
78 kJapaneseInputMethodOrLayout,
79 XK_Zenkaku_Hankaku,
80 0x0,
81 true,
82 },
83 {
84 { "mozc-hangul", "xkb:kr:kr104:kor" },
85 kKoreanInputMethodOrLayout,
86 XK_Hangul,
87 0x0,
88 true,
89 },
90 {
91 { "mozc-hangul", "xkb:kr:kr104:kor" },
92 kKoreanInputMethodOrLayout,
93 XK_space,
94 ShiftMask,
95 true,
96 },
48 }; 97 };
49 98
50 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the 99 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the
51 // property with |new_prop|. Returns true if such a property is found. 100 // property with |new_prop|. Returns true if such a property is found.
52 bool FindAndUpdateProperty( 101 bool FindAndUpdateProperty(
53 const chromeos::input_method::ImeProperty& new_prop, 102 const chromeos::input_method::ImeProperty& new_prop,
54 chromeos::input_method::ImePropertyList* prop_list) { 103 chromeos::input_method::ImePropertyList* prop_list) {
55 for (size_t i = 0; i < prop_list->size(); ++i) { 104 for (size_t i = 0; i < prop_list->size(); ++i) {
56 chromeos::input_method::ImeProperty& prop = prop_list->at(i); 105 chromeos::input_method::ImeProperty& prop = prop_list->at(i);
57 if (prop.key == new_prop.key) { 106 if (prop.key == new_prop.key) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // details. 146 // details.
98 notification_registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, 147 notification_registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
99 NotificationService::AllSources()); 148 NotificationService::AllSources());
100 149
101 ibus_controller_ = IBusController::Create(); 150 ibus_controller_ = IBusController::Create();
102 // The observer should be added before Connect() so we can capture the 151 // The observer should be added before Connect() so we can capture the
103 // initial connection change. 152 // initial connection change.
104 ibus_controller_->AddObserver(this); 153 ibus_controller_->AddObserver(this);
105 ibus_controller_->Connect(); 154 ibus_controller_->Connect();
106 155
156 // Initialize engine_hotkeys_.
157 for (size_t i = 0; i < arraysize(kEngineSpecificHotkeySettings); ++i) {
158 const char* const* input_method_ids =
159 kEngineSpecificHotkeySettings[i].input_method_ids;
160 const size_t input_method_ids_len =
161 arraysize(kEngineSpecificHotkeySettings[i].input_method_ids);
162 for (size_t j = 0; j < input_method_ids_len && input_method_ids[j]; ++j) {
163 engine_hotkeys_.insert(std::make_pair(
164 input_method_ids[j], &kEngineSpecificHotkeySettings[i]));
165 }
166 }
167
168 // Register global input method hotkeys: Control+space and Shift+Alt.
107 InitHotkeyManager(); 169 InitHotkeyManager();
108 } 170 }
109 171
110 virtual ~InputMethodManagerImpl() { 172 virtual ~InputMethodManagerImpl() {
111 hotkey_manager_.RemoveObserver(this); 173 hotkey_manager_.RemoveObserver(this);
112 ibus_controller_->RemoveObserver(this); 174 ibus_controller_->RemoveObserver(this);
113 } 175 }
114 176
115 virtual void AddObserver(InputMethodManager::Observer* observer) { 177 virtual void AddObserver(InputMethodManager::Observer* observer) {
116 if (!observers_.size()) { 178 if (!observers_.size()) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 // input methods cache |active_input_method_ids_| here. We need to 278 // input methods cache |active_input_method_ids_| here. We need to
217 // update the cache before actually flushing the config. since we need 279 // update the cache before actually flushing the config. since we need
218 // to return active input methods from GetActiveInputMethods() before 280 // to return active input methods from GetActiveInputMethods() before
219 // the input method daemon starts. For instance, we need to show the 281 // the input method daemon starts. For instance, we need to show the
220 // list of available input methods (keyboard layouts) on the login 282 // list of available input methods (keyboard layouts) on the login
221 // screen before the input method starts. 283 // screen before the input method starts.
222 if (section == language_prefs::kGeneralSectionName && 284 if (section == language_prefs::kGeneralSectionName &&
223 config_name == language_prefs::kPreloadEnginesConfigName && 285 config_name == language_prefs::kPreloadEnginesConfigName &&
224 value.type == ImeConfigValue::kValueTypeStringList) { 286 value.type == ImeConfigValue::kValueTypeStringList) {
225 active_input_method_ids_ = value.string_list_value; 287 active_input_method_ids_ = value.string_list_value;
288 UpdateEngineSpecificHotkeys();
mazda 2011/09/12 10:02:54 Is it OK that UpdateEngineSpecificHotkeys is calle
Yusuke Sato 2011/09/12 11:46:05 For now it's okay since hotkey information for an
226 289
227 std::map<std::string, InputMethodDescriptor>::const_iterator ix; 290 std::map<std::string, InputMethodDescriptor>::const_iterator ix;
228 for (ix = extra_input_method_ids_.begin(); 291 for (ix = extra_input_method_ids_.begin();
229 ix != extra_input_method_ids_.end(); ++ix) { 292 ix != extra_input_method_ids_.end(); ++ix) {
230 active_input_method_ids_.push_back(ix->first); 293 active_input_method_ids_.push_back(ix->first);
231 } 294 }
232 } 295 }
233 296
234 // Before calling FlushImeConfig(), start input method process if necessary. 297 // Before calling FlushImeConfig(), start input method process if necessary.
235 MaybeStartInputMethodDaemon(section, config_name, value); 298 MaybeStartInputMethodDaemon(section, config_name, value);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 virtual void ClearAllVirtualKeyboardPreferences() { 405 virtual void ClearAllVirtualKeyboardPreferences() {
343 virtual_keyboard_selector_.ClearAllUserPreferences(); 406 virtual_keyboard_selector_.ClearAllUserPreferences();
344 UpdateVirtualKeyboardUI(); 407 UpdateVirtualKeyboardUI();
345 } 408 }
346 409
347 virtual HotkeyManager* GetHotkeyManager() { 410 virtual HotkeyManager* GetHotkeyManager() {
348 return &hotkey_manager_; 411 return &hotkey_manager_;
349 } 412 }
350 413
351 virtual void HotkeyPressed(HotkeyManager* manager, int event_id) { 414 virtual void HotkeyPressed(HotkeyManager* manager, int event_id) {
352 switch (HotkeyEvents(event_id)) { 415 const HotkeyEvent event = HotkeyEvent(event_id);
416 switch (event) {
353 case kPreviousInputMethod: 417 case kPreviousInputMethod:
354 SwitchToPreviousInputMethod(); 418 SwitchToPreviousInputMethod();
355 break; 419 break;
356 case kNextInputMethod: 420 case kNextInputMethod:
357 SwitchToNextInputMethod(); 421 SwitchToNextInputMethod();
358 break; 422 break;
423 case kJapaneseInputMethod:
424 case kJapaneseLayout:
425 case kJapaneseInputMethodOrLayout:
426 case kKoreanInputMethodOrLayout:
427 SwitchToInputMethod(event);
mazda 2011/09/12 10:02:54 default case.
Yusuke Sato 2011/09/12 11:46:05 Since HotkeyEvent is an enum, adding default: is n
428 break;
359 } 429 }
360 // TODO(yusukes): handle engine specific hotkeys like Henkan, Muhenkan, and
361 // Hangul.
362 } 430 }
363 431
364 static InputMethodManagerImpl* GetInstance() { 432 static InputMethodManagerImpl* GetInstance() {
365 return Singleton<InputMethodManagerImpl, 433 return Singleton<InputMethodManagerImpl,
366 DefaultSingletonTraits<InputMethodManagerImpl> >::get(); 434 DefaultSingletonTraits<InputMethodManagerImpl> >::get();
367 } 435 }
368 436
369 private: 437 private:
370 friend struct DefaultSingletonTraits<InputMethodManagerImpl>; 438 friend struct DefaultSingletonTraits<InputMethodManagerImpl>;
371 439
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 ShiftMask | Mod1Mask, 1022 ShiftMask | Mod1Mask,
955 false); 1023 false);
956 hotkey_manager_.AddHotkey(kNextInputMethod, 1024 hotkey_manager_.AddHotkey(kNextInputMethod,
957 XK_Meta_L, 1025 XK_Meta_L,
958 ShiftMask | Mod1Mask, 1026 ShiftMask | Mod1Mask,
959 false); 1027 false);
960 hotkey_manager_.AddHotkey(kNextInputMethod, 1028 hotkey_manager_.AddHotkey(kNextInputMethod,
961 XK_Meta_R, 1029 XK_Meta_R,
962 ShiftMask | Mod1Mask, 1030 ShiftMask | Mod1Mask,
963 false); 1031 false);
1032 // Engine specific hotkeys will be added in SetImeConfig().
964 1033
965 // TODO(yusukes): Support engine specific hotkeys like XK_Henkan, Muhenkan,
966 // and Hangul.
967 hotkey_manager_.AddObserver(this); 1034 hotkey_manager_.AddObserver(this);
968 } 1035 }
969 1036
1037 void UpdateEngineSpecificHotkeys() {
1038 // Remove all engine specific hotkeys first.
1039 for (size_t i = 0; i < arraysize(kEngineSpecificHotkeySettings); ++i) {
1040 hotkey_manager_.RemoveHotkey(kEngineSpecificHotkeySettings[i].event_id);
1041 }
1042 for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
1043 typedef std::map<std::string,
1044 const EngineSpecificHotkeySetting*>::const_iterator Iter;
1045 std::pair<Iter, Iter> result = engine_hotkeys_.equal_range(
1046 active_input_method_ids_[i]);
1047 for (Iter iter = result.first; iter != result.second; ++iter) {
1048 hotkey_manager_.AddHotkey(iter->second->event_id,
1049 iter->second->keysym,
1050 iter->second->modifiers,
1051 iter->second->trigger_on_press);
1052 }
1053 }
1054 }
1055
970 // Handles "Shift+Alt" hotkey. 1056 // Handles "Shift+Alt" hotkey.
971 void SwitchToNextInputMethod() { 1057 void SwitchToNextInputMethod() {
972 // Sanity checks. 1058 // Sanity checks.
973 if (active_input_method_ids_.empty()) { 1059 if (active_input_method_ids_.empty()) {
974 LOG(ERROR) << "active input method is empty"; 1060 LOG(ERROR) << "active input method is empty";
975 return; 1061 return;
976 } 1062 }
977 if (current_input_method_.id().empty()) { 1063 if (current_input_method_.id().empty()) {
978 LOG(ERROR) << "current_input_method_ is unknown"; 1064 LOG(ERROR) << "current_input_method_ is unknown";
979 return; 1065 return;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 active_input_method_ids_.end(), 1098 active_input_method_ids_.end(),
1013 previous_input_method_.id()); 1099 previous_input_method_.id());
1014 if (iter == active_input_method_ids_.end()) { 1100 if (iter == active_input_method_ids_.end()) {
1015 // previous_input_method_ is not supported. 1101 // previous_input_method_ is not supported.
1016 SwitchToNextInputMethod(); 1102 SwitchToNextInputMethod();
1017 } else { 1103 } else {
1018 ChangeInputMethod(*iter); 1104 ChangeInputMethod(*iter);
1019 } 1105 }
1020 } 1106 }
1021 1107
1108 // Handles engine specific hotkeys like XK_Henkan.
1109 void SwitchToInputMethod(HotkeyEvent event) {
1110 // Sanity check.
1111 if (active_input_method_ids_.empty()) {
1112 LOG(ERROR) << "active input method is empty";
1113 return;
1114 }
1115
1116 const char* const* input_method_ids_to_switch = NULL;
1117 size_t input_method_ids_to_switch_len = 0;
1118
1119 // Get the list of input method ids for |event_id|. For example, get
1120 // { "mozc-hangul", "xkb:kr:kr104:kor" } for kKoreanInputMethodOrLayout.
1121 switch (event) {
1122 case kPreviousInputMethod:
1123 case kNextInputMethod: {
1124 break;
mazda 2011/09/12 10:02:54 Are these two error case?
Yusuke Sato 2011/09/12 11:46:05 added a comment.
1125 }
1126 case kJapaneseInputMethod:
1127 case kJapaneseLayout:
1128 case kJapaneseInputMethodOrLayout:
1129 case kKoreanInputMethodOrLayout: {
1130 const size_t index = static_cast<size_t>(event) - 2;
Zachary Kuznia 2011/09/12 09:48:07 This line looks scary. Please give it a reassurin
Yusuke Sato 2011/09/12 11:46:05 Probably this was too error-prone. I've written th
1131 DCHECK(event == kEngineSpecificHotkeySettings[index].event_id);
1132 input_method_ids_to_switch =
1133 kEngineSpecificHotkeySettings[index].input_method_ids;
1134 input_method_ids_to_switch_len =
1135 arraysize(kEngineSpecificHotkeySettings[index].input_method_ids);
1136 break;
1137 }
1138 }
1139 if (!input_method_ids_to_switch) {
mazda 2011/09/12 10:02:54 How about moving this to the default case of the s
Yusuke Sato 2011/09/12 11:46:05 ditto. I prefer not to use default: in order to ke
1140 LOG(ERROR) << "Unknown event: " << event;
1141 return;
1142 }
1143
1144 // Obtain the intersection of input_method_ids_to_switch and
1145 // active_input_method_ids_. The order of IDs in active_input_method_ids_ is
1146 // preserved.
1147 std::vector<std::string> ids;
1148 for (size_t i = 0; i < input_method_ids_to_switch_len; ++i) {
1149 const char* id = input_method_ids_to_switch[i];
1150 if (id && std::find(active_input_method_ids_.begin(),
1151 active_input_method_ids_.end(),
1152 id) != active_input_method_ids_.end()) {
1153 ids.push_back(id);
1154 }
1155 }
1156 if (ids.empty()) {
1157 LOG(ERROR) << "No input method for " << event << " is active";
1158 return;
1159 }
1160
1161 // If current_input_method_ is not in ids, switch to ids[0]. If
1162 // current_input_method_ is ids[N], switch to ids[N+1].
1163 std::vector<std::string>::const_iterator iter =
1164 std::find(ids.begin(), ids.end(), current_input_method_.id());
1165 if (iter != ids.end()) {
1166 ++iter;
1167 }
1168 if (iter == ids.end()) {
1169 iter = ids.begin();
1170 }
1171 ChangeInputMethod(*iter);
1172 }
1173
1022 // A reference to the language api, to allow callbacks when the input method 1174 // A reference to the language api, to allow callbacks when the input method
1023 // status changes. 1175 // status changes.
1024 IBusController* ibus_controller_; 1176 IBusController* ibus_controller_;
1025 ObserverList<InputMethodManager::Observer> observers_; 1177 ObserverList<InputMethodManager::Observer> observers_;
1026 ObserverList<VirtualKeyboardObserver> virtual_keyboard_observers_; 1178 ObserverList<VirtualKeyboardObserver> virtual_keyboard_observers_;
1027 1179
1028 // The input method which was/is selected. 1180 // The input method which was/is selected.
1029 InputMethodDescriptor previous_input_method_; 1181 InputMethodDescriptor previous_input_method_;
1030 InputMethodDescriptor current_input_method_; 1182 InputMethodDescriptor current_input_method_;
1031 1183
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 // An object which keeps a list of available virtual keyboards. 1233 // An object which keeps a list of available virtual keyboards.
1082 VirtualKeyboardSelector virtual_keyboard_selector_; 1234 VirtualKeyboardSelector virtual_keyboard_selector_;
1083 1235
1084 // The active input method ids cache. 1236 // The active input method ids cache.
1085 std::vector<std::string> active_input_method_ids_; 1237 std::vector<std::string> active_input_method_ids_;
1086 1238
1087 // Extra input methods that have been explicitly added to the menu, such as 1239 // Extra input methods that have been explicitly added to the menu, such as
1088 // those created by extension. 1240 // those created by extension.
1089 std::map<std::string, InputMethodDescriptor> extra_input_method_ids_; 1241 std::map<std::string, InputMethodDescriptor> extra_input_method_ids_;
1090 1242
1243 // A muitlmap from input method id to engine specific hotkey information.
1244 // e.g. "mozc-jp" to XK_ZenkakuHankaku, "mozc-jp" to XK_Henkan.
1245 std::multimap<std::string,
1246 const EngineSpecificHotkeySetting*> engine_hotkeys_;
1091 // An object which detects Control+space and Shift+Alt key presses. 1247 // An object which detects Control+space and Shift+Alt key presses.
1092 HotkeyManager hotkey_manager_; 1248 HotkeyManager hotkey_manager_;
1093 1249
1094 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl); 1250 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
1095 }; 1251 };
1096 1252
1097 // static 1253 // static
1098 InputMethodManager* InputMethodManager::GetInstance() { 1254 InputMethodManager* InputMethodManager::GetInstance() {
1099 return InputMethodManagerImpl::GetInstance(); 1255 return InputMethodManagerImpl::GetInstance();
1100 } 1256 }
1101 1257
1102 } // namespace input_method 1258 } // namespace input_method
1103 } // namespace chromeos 1259 } // namespace chromeos
1104 1260
1105 // Allows InvokeLater without adding refcounting. This class is a Singleton and 1261 // Allows InvokeLater without adding refcounting. This class is a Singleton and
1106 // won't be deleted until it's last InvokeLater is run. 1262 // won't be deleted until it's last InvokeLater is run.
1107 DISABLE_RUNNABLE_METHOD_REFCOUNT( 1263 DISABLE_RUNNABLE_METHOD_REFCOUNT(
1108 chromeos::input_method::InputMethodManagerImpl); 1264 chromeos::input_method::InputMethodManagerImpl);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698