| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_engine.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_engine.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include "chrome/browser/chromeos/input_method/input_method_engine_ibus.h" |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/string_util.h" | |
| 12 #include "chrome/browser/chromeos/input_method/ibus_engine_controller.h" | |
| 13 #include "chrome/browser/chromeos/input_method/ibus_keymap.h" | |
| 14 #include "chrome/browser/chromeos/input_method/input_method_manager.h" | |
| 15 #include "chrome/browser/chromeos/input_method/input_method_util.h" | |
| 16 | 8 |
| 17 namespace chromeos { | 9 namespace chromeos { |
| 18 | 10 |
| 19 const char* kExtensionImePrefix = "_ext_ime_"; | |
| 20 const char* kErrorNotActive = "IME is not active"; | |
| 21 const char* kErrorWrongContext = "Context is not active"; | |
| 22 const char* kCandidateNotFound = "Candidate not found"; | |
| 23 | |
| 24 InputMethodEngine::KeyboardEvent::KeyboardEvent() | 11 InputMethodEngine::KeyboardEvent::KeyboardEvent() |
| 25 : alt_key(false), | 12 : alt_key(false), |
| 26 ctrl_key(false), | 13 ctrl_key(false), |
| 27 shift_key(false) { | 14 shift_key(false) { |
| 28 } | 15 } |
| 29 | 16 |
| 30 InputMethodEngine::KeyboardEvent::~KeyboardEvent() { | 17 InputMethodEngine::KeyboardEvent::~KeyboardEvent() { |
| 31 } | 18 } |
| 32 | 19 |
| 33 InputMethodEngine::MenuItem::MenuItem() { | 20 InputMethodEngine::MenuItem::MenuItem() { |
| 34 } | 21 } |
| 35 | 22 |
| 36 InputMethodEngine::MenuItem::~MenuItem() { | 23 InputMethodEngine::MenuItem::~MenuItem() { |
| 37 } | 24 } |
| 38 | 25 |
| 39 InputMethodEngine::Candidate::Candidate() { | 26 InputMethodEngine::Candidate::Candidate() { |
| 40 } | 27 } |
| 41 | 28 |
| 42 InputMethodEngine::Candidate::~Candidate() { | 29 InputMethodEngine::Candidate::~Candidate() { |
| 43 } | 30 } |
| 44 | 31 |
| 45 InputMethodEngine::Observer::~Observer() { | 32 InputMethodEngine::Observer::~Observer() { |
| 46 } | 33 } |
| 47 | 34 |
| 48 class InputMethodEngineImpl | |
| 49 : public InputMethodEngine, | |
| 50 public input_method::IBusEngineController::Observer { | |
| 51 public: | |
| 52 InputMethodEngineImpl() | |
| 53 : observer_(NULL), active_(false), next_context_id_(1), | |
| 54 context_id_(-1) {} | |
| 55 | |
| 56 ~InputMethodEngineImpl() { | |
| 57 input_method::InputMethodManager* manager = | |
| 58 input_method::InputMethodManager::GetInstance(); | |
| 59 manager->RemoveInputMethodExtension(ibus_id_); | |
| 60 } | |
| 61 | |
| 62 bool Init(InputMethodEngine::Observer* observer, | |
| 63 const char* engine_name, | |
| 64 const char* extension_id, | |
| 65 const char* engine_id, | |
| 66 const char* description, | |
| 67 const char* language, | |
| 68 const std::vector<std::string>& layouts, | |
| 69 std::string* error); | |
| 70 | |
| 71 virtual bool SetComposition(int context_id, | |
| 72 const char* text, int selection_start, | |
| 73 int selection_end, int cursor, | |
| 74 const std::vector<SegmentInfo>& segments, | |
| 75 std::string* error); | |
| 76 virtual bool ClearComposition(int context_id, | |
| 77 std::string* error); | |
| 78 virtual bool CommitText(int context_id, | |
| 79 const char* text, std::string* error); | |
| 80 virtual bool SetCandidateWindowVisible(bool visible, std::string* error); | |
| 81 virtual void SetCandidateWindowCursorVisible(bool visible); | |
| 82 virtual void SetCandidateWindowVertical(bool vertical); | |
| 83 virtual void SetCandidateWindowPageSize(int size); | |
| 84 virtual void SetCandidateWindowAuxText(const char* text); | |
| 85 virtual void SetCandidateWindowAuxTextVisible(bool visible); | |
| 86 virtual bool SetCandidates(int context_id, | |
| 87 const std::vector<Candidate>& candidates, | |
| 88 std::string* error); | |
| 89 virtual bool SetCursorPosition(int context_id, int candidate_id, | |
| 90 std::string* error); | |
| 91 virtual bool SetMenuItems(const std::vector<MenuItem>& items); | |
| 92 virtual bool UpdateMenuItems(const std::vector<MenuItem>& items); | |
| 93 virtual bool IsActive() const { | |
| 94 return active_; | |
| 95 } | |
| 96 virtual void KeyEventDone(input_method::KeyEventHandle* key_data, | |
| 97 bool handled); | |
| 98 | |
| 99 virtual void OnReset(); | |
| 100 virtual void OnEnable(); | |
| 101 virtual void OnDisable(); | |
| 102 virtual void OnFocusIn(); | |
| 103 virtual void OnFocusOut(); | |
| 104 virtual void OnKeyEvent(bool key_press, unsigned int keyval, | |
| 105 unsigned int keycode, bool alt_key, bool ctrl_key, | |
| 106 bool shift_key, | |
| 107 input_method::KeyEventHandle* key_data); | |
| 108 virtual void OnPropertyActivate(const char* name, unsigned int state); | |
| 109 virtual void OnCandidateClicked(unsigned int index, unsigned int button, | |
| 110 unsigned int state); | |
| 111 private: | |
| 112 bool MenuItemToProperty( | |
| 113 const MenuItem& item, | |
| 114 input_method::IBusEngineController::EngineProperty* property); | |
| 115 | |
| 116 // Pointer to the object recieving events for this IME. | |
| 117 InputMethodEngine::Observer* observer_; | |
| 118 | |
| 119 // Connection to IBus. | |
| 120 scoped_ptr<input_method::IBusEngineController> connection_; | |
| 121 | |
| 122 // True when this IME is active, false if deactive. | |
| 123 bool active_; | |
| 124 | |
| 125 // Next id that will be assigned to a context. | |
| 126 int next_context_id_; | |
| 127 | |
| 128 // ID that is used for the current input context. False if there is no focus. | |
| 129 int context_id_; | |
| 130 | |
| 131 // User specified id of this IME. | |
| 132 std::string engine_id_; | |
| 133 | |
| 134 // ID used by ibus to reference this IME. | |
| 135 std::string ibus_id_; | |
| 136 | |
| 137 // Mapping of candidate index to candidate id. | |
| 138 std::vector<int> candidate_ids_; | |
| 139 | |
| 140 // Mapping of candidate id to index. | |
| 141 std::map<int, int> candidate_indexes_; | |
| 142 }; | |
| 143 | |
| 144 bool InputMethodEngineImpl::Init(InputMethodEngine::Observer* observer, | |
| 145 const char* engine_name, | |
| 146 const char* extension_id, | |
| 147 const char* engine_id, | |
| 148 const char* description, | |
| 149 const char* language, | |
| 150 const std::vector<std::string>& layouts, | |
| 151 std::string* error) { | |
| 152 ibus_id_ = kExtensionImePrefix; | |
| 153 ibus_id_ += extension_id; | |
| 154 ibus_id_ += engine_id; | |
| 155 | |
| 156 std::string layout; | |
| 157 input_method::InputMethodManager* manager = | |
| 158 input_method::InputMethodManager::GetInstance(); | |
| 159 | |
| 160 if (!layouts.empty()) { | |
| 161 layout = JoinString(layouts, ','); | |
| 162 } else { | |
| 163 const std::string fallback_id = | |
| 164 manager->GetInputMethodUtil()->GetHardwareInputMethodId(); | |
| 165 const input_method::InputMethodDescriptor* fallback_desc = | |
| 166 manager->GetInputMethodUtil()->GetInputMethodDescriptorFromId( | |
| 167 fallback_id); | |
| 168 layout = fallback_desc->keyboard_layout(); | |
| 169 } | |
| 170 | |
| 171 connection_.reset(input_method::IBusEngineController::Create(this, | |
| 172 ibus_id_.c_str(), | |
| 173 engine_name, | |
| 174 description, | |
| 175 language, | |
| 176 layout.c_str())); | |
| 177 if (!connection_.get()) { | |
| 178 *error = "ConnectInputMethodExtension() failed."; | |
| 179 return false; | |
| 180 } | |
| 181 | |
| 182 observer_ = observer; | |
| 183 engine_id_ = engine_id; | |
| 184 manager->AddInputMethodExtension(ibus_id_, engine_name, layouts, language); | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 bool InputMethodEngineImpl::SetComposition( | |
| 189 int context_id, | |
| 190 const char* text, | |
| 191 int selection_start, | |
| 192 int selection_end, | |
| 193 int cursor, | |
| 194 const std::vector<SegmentInfo>& segments, | |
| 195 std::string* error) { | |
| 196 if (!active_) { | |
| 197 *error = kErrorNotActive; | |
| 198 return false; | |
| 199 } | |
| 200 if (context_id != context_id_ || context_id_ == -1) { | |
| 201 *error = kErrorWrongContext; | |
| 202 return false; | |
| 203 } | |
| 204 | |
| 205 connection_->SetPreeditText(text, cursor); | |
| 206 // TODO: Add support for displaying selected text in the composition string. | |
| 207 for (std::vector<SegmentInfo>::const_iterator segment = segments.begin(); | |
| 208 segment != segments.end(); ++segment) { | |
| 209 int style; | |
| 210 switch (segment->style) { | |
| 211 case SEGMENT_STYLE_UNDERLINE: | |
| 212 style = input_method::IBusEngineController::UNDERLINE_SINGLE; | |
| 213 break; | |
| 214 case SEGMENT_STYLE_DOUBLE_UNDERLINE: | |
| 215 style = input_method::IBusEngineController::UNDERLINE_DOUBLE; | |
| 216 break; | |
| 217 | |
| 218 default: | |
| 219 continue; | |
| 220 } | |
| 221 | |
| 222 connection_->SetPreeditUnderline(segment->start, segment->end, style); | |
| 223 } | |
| 224 return true; | |
| 225 } | |
| 226 | |
| 227 bool InputMethodEngineImpl::ClearComposition(int context_id, | |
| 228 std::string* error) { | |
| 229 if (!active_) { | |
| 230 *error = kErrorNotActive; | |
| 231 return false; | |
| 232 } | |
| 233 if (context_id != context_id_ || context_id_ == -1) { | |
| 234 *error = kErrorWrongContext; | |
| 235 return false; | |
| 236 } | |
| 237 | |
| 238 connection_->SetPreeditText("", 0); | |
| 239 return true; | |
| 240 } | |
| 241 | |
| 242 bool InputMethodEngineImpl::CommitText(int context_id, | |
| 243 const char* text, std::string* error) { | |
| 244 if (context_id != context_id_ || context_id_ == -1) { | |
| 245 *error = kErrorWrongContext; | |
| 246 return false; | |
| 247 } | |
| 248 if (!active_) { | |
| 249 // TODO: Commit the text anyways. | |
| 250 *error = kErrorNotActive; | |
| 251 return false; | |
| 252 } | |
| 253 | |
| 254 connection_->CommitText(text); | |
| 255 return true; | |
| 256 } | |
| 257 | |
| 258 bool InputMethodEngineImpl::SetCandidateWindowVisible(bool visible, | |
| 259 std::string* error) { | |
| 260 if (!active_) { | |
| 261 *error = kErrorNotActive; | |
| 262 return false; | |
| 263 } | |
| 264 | |
| 265 connection_->SetTableVisible(visible); | |
| 266 return true; | |
| 267 } | |
| 268 | |
| 269 void InputMethodEngineImpl::SetCandidateWindowCursorVisible(bool visible) { | |
| 270 connection_->SetCursorVisible(visible); | |
| 271 } | |
| 272 | |
| 273 void InputMethodEngineImpl::SetCandidateWindowVertical(bool vertical) { | |
| 274 connection_->SetOrientationVertical(vertical); | |
| 275 } | |
| 276 | |
| 277 void InputMethodEngineImpl::SetCandidateWindowPageSize(int size) { | |
| 278 connection_->SetPageSize(size); | |
| 279 } | |
| 280 | |
| 281 void InputMethodEngineImpl::SetCandidateWindowAuxText(const char* text) { | |
| 282 connection_->SetCandidateAuxText(text); | |
| 283 } | |
| 284 | |
| 285 void InputMethodEngineImpl::SetCandidateWindowAuxTextVisible(bool visible) { | |
| 286 connection_->SetCandidateAuxTextVisible(visible); | |
| 287 } | |
| 288 | |
| 289 bool InputMethodEngineImpl::SetCandidates( | |
| 290 int context_id, const std::vector<Candidate>& candidates, | |
| 291 std::string* error) { | |
| 292 if (!active_) { | |
| 293 *error = kErrorNotActive; | |
| 294 return false; | |
| 295 } | |
| 296 if (context_id != context_id_ || context_id_ == -1) { | |
| 297 *error = kErrorWrongContext; | |
| 298 return false; | |
| 299 } | |
| 300 | |
| 301 // TODO: Nested candidates | |
| 302 std::vector<input_method::IBusEngineController::Candidate> ibus_candidates; | |
| 303 | |
| 304 candidate_ids_.clear(); | |
| 305 candidate_indexes_.clear(); | |
| 306 for (std::vector<Candidate>::const_iterator ix = candidates.begin(); | |
| 307 ix != candidates.end(); ++ix) { | |
| 308 ibus_candidates.push_back(input_method::IBusEngineController::Candidate()); | |
| 309 ibus_candidates.back().value = ix->value; | |
| 310 ibus_candidates.back().label = ix->label; | |
| 311 ibus_candidates.back().annotation = ix->annotation; | |
| 312 | |
| 313 // Store a mapping from the user defined ID to the candidate index. | |
| 314 candidate_indexes_[ix->id] = candidate_ids_.size(); | |
| 315 candidate_ids_.push_back(ix->id); | |
| 316 } | |
| 317 connection_->SetCandidates(ibus_candidates); | |
| 318 return true; | |
| 319 } | |
| 320 | |
| 321 bool InputMethodEngineImpl::SetCursorPosition(int context_id, int candidate_id, | |
| 322 std::string* error) { | |
| 323 if (!active_) { | |
| 324 *error = kErrorNotActive; | |
| 325 return false; | |
| 326 } | |
| 327 if (context_id != context_id_ || context_id_ == -1) { | |
| 328 *error = kErrorWrongContext; | |
| 329 return false; | |
| 330 } | |
| 331 | |
| 332 std::map<int, int>::const_iterator position = | |
| 333 candidate_indexes_.find(candidate_id); | |
| 334 if (position == candidate_indexes_.end()) { | |
| 335 *error = kCandidateNotFound; | |
| 336 return false; | |
| 337 } | |
| 338 | |
| 339 connection_->SetCursorPosition(position->second); | |
| 340 return true; | |
| 341 } | |
| 342 | |
| 343 bool InputMethodEngineImpl::SetMenuItems(const std::vector<MenuItem>& items) { | |
| 344 std::vector<input_method::IBusEngineController::EngineProperty*> properties; | |
| 345 | |
| 346 for (std::vector<MenuItem>::const_iterator item = items.begin(); | |
| 347 item != items.end(); ++item) { | |
| 348 input_method::IBusEngineController::EngineProperty* property = | |
| 349 new input_method::IBusEngineController::EngineProperty; | |
| 350 if (!MenuItemToProperty(*item, property)) { | |
| 351 delete property; | |
| 352 DVLOG(1) << "Bad menu item"; | |
| 353 return false; | |
| 354 } | |
| 355 properties.push_back(property); | |
| 356 } | |
| 357 return connection_->RegisterProperties(properties); | |
| 358 } | |
| 359 | |
| 360 bool InputMethodEngineImpl::MenuItemToProperty( | |
| 361 const MenuItem& item, | |
| 362 input_method::IBusEngineController::EngineProperty* property) { | |
| 363 property->key = item.id; | |
| 364 property->label = item.label; | |
| 365 property->visible = item.visible; | |
| 366 property->sensitive = item.enabled; | |
| 367 property->checked = item.checked; | |
| 368 | |
| 369 if (!item.children.empty()) { | |
| 370 property->type = input_method::IBusEngineController::PROPERTY_TYPE_MENU; | |
| 371 } else { | |
| 372 switch (item.style) { | |
| 373 case MENU_ITEM_STYLE_NONE: | |
| 374 property->type = | |
| 375 input_method::IBusEngineController::PROPERTY_TYPE_NORMAL; | |
| 376 break; | |
| 377 case MENU_ITEM_STYLE_CHECK: | |
| 378 property->type = | |
| 379 input_method::IBusEngineController::PROPERTY_TYPE_TOGGLE; | |
| 380 break; | |
| 381 case MENU_ITEM_STYLE_RADIO: | |
| 382 property->type = | |
| 383 input_method::IBusEngineController::PROPERTY_TYPE_RADIO; | |
| 384 break; | |
| 385 case MENU_ITEM_STYLE_SEPARATOR: | |
| 386 property->type = | |
| 387 input_method::IBusEngineController::PROPERTY_TYPE_SEPARATOR; | |
| 388 break; | |
| 389 } | |
| 390 } | |
| 391 | |
| 392 property->modified = 0; | |
| 393 if (item.modified & MENU_ITEM_MODIFIED_LABEL) { | |
| 394 property->modified |= | |
| 395 input_method::IBusEngineController::PROPERTY_MODIFIED_LABEL; | |
| 396 } | |
| 397 if (item.modified & MENU_ITEM_MODIFIED_STYLE) { | |
| 398 property->modified |= | |
| 399 input_method::IBusEngineController::PROPERTY_MODIFIED_TYPE; | |
| 400 } | |
| 401 if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) { | |
| 402 property->modified |= | |
| 403 input_method::IBusEngineController::PROPERTY_MODIFIED_VISIBLE; | |
| 404 } | |
| 405 if (item.modified & MENU_ITEM_MODIFIED_ENABLED) { | |
| 406 property->modified |= | |
| 407 input_method::IBusEngineController::PROPERTY_MODIFIED_SENSITIVE; | |
| 408 } | |
| 409 if (item.modified & MENU_ITEM_MODIFIED_CHECKED) { | |
| 410 property->modified |= | |
| 411 input_method::IBusEngineController::PROPERTY_MODIFIED_CHECKED; | |
| 412 } | |
| 413 | |
| 414 for (std::vector<MenuItem>::const_iterator child = item.children.begin(); | |
| 415 child != item.children.end(); ++child) { | |
| 416 input_method::IBusEngineController::EngineProperty* new_property = | |
| 417 new input_method::IBusEngineController::EngineProperty; | |
| 418 if (!MenuItemToProperty(*child, new_property)) { | |
| 419 delete new_property; | |
| 420 DVLOG(1) << "Bad menu item child"; | |
| 421 return false; | |
| 422 } | |
| 423 property->children.push_back(new_property); | |
| 424 } | |
| 425 | |
| 426 return true; | |
| 427 } | |
| 428 | |
| 429 bool InputMethodEngineImpl::UpdateMenuItems( | |
| 430 const std::vector<MenuItem>& items) { | |
| 431 std::vector<input_method::IBusEngineController::EngineProperty*> properties; | |
| 432 | |
| 433 for (std::vector<MenuItem>::const_iterator item = items.begin(); | |
| 434 item != items.end(); ++item) { | |
| 435 input_method::IBusEngineController::EngineProperty* new_property = | |
| 436 new input_method::IBusEngineController::EngineProperty(); | |
| 437 if (!MenuItemToProperty(*item, new_property)) { | |
| 438 DVLOG(1) << "Bad menu item"; | |
| 439 delete new_property; | |
| 440 return false; | |
| 441 } | |
| 442 properties.push_back(new_property); | |
| 443 } | |
| 444 return connection_->UpdateProperties(properties); | |
| 445 } | |
| 446 | |
| 447 void InputMethodEngineImpl::KeyEventDone(input_method::KeyEventHandle* key_data, | |
| 448 bool handled) { | |
| 449 connection_->KeyEventDone(key_data, handled); | |
| 450 } | |
| 451 | |
| 452 void InputMethodEngineImpl::OnReset() { | |
| 453 // Ignored | |
| 454 } | |
| 455 | |
| 456 void InputMethodEngineImpl::OnEnable() { | |
| 457 active_ = true; | |
| 458 observer_->OnActivate(engine_id_); | |
| 459 } | |
| 460 | |
| 461 void InputMethodEngineImpl::OnDisable() { | |
| 462 active_ = false; | |
| 463 observer_->OnDeactivated(engine_id_); | |
| 464 } | |
| 465 | |
| 466 void InputMethodEngineImpl::OnFocusIn() { | |
| 467 context_id_ = next_context_id_; | |
| 468 ++next_context_id_; | |
| 469 | |
| 470 InputContext context; | |
| 471 context.id = context_id_; | |
| 472 // TODO: Other types | |
| 473 context.type = "text"; | |
| 474 | |
| 475 observer_->OnFocus(context); | |
| 476 } | |
| 477 | |
| 478 void InputMethodEngineImpl::OnFocusOut() { | |
| 479 int context_id = context_id_; | |
| 480 context_id_ = -1; | |
| 481 observer_->OnBlur(context_id); | |
| 482 } | |
| 483 | |
| 484 void InputMethodEngineImpl::OnKeyEvent(bool key_press, unsigned int keyval, | |
| 485 unsigned int keycode, bool alt_key, | |
| 486 bool ctrl_key, bool shift_key, | |
| 487 input_method::KeyEventHandle* key_data) { | |
| 488 KeyboardEvent event; | |
| 489 event.type = key_press ? "keydown" : "keyup"; | |
| 490 event.key = input_method::GetIBusKey(keyval); | |
| 491 event.alt_key = alt_key; | |
| 492 event.ctrl_key = ctrl_key; | |
| 493 event.shift_key = shift_key; | |
| 494 observer_->OnKeyEvent(engine_id_, event, key_data); | |
| 495 } | |
| 496 | |
| 497 void InputMethodEngineImpl::OnPropertyActivate(const char* name, | |
| 498 unsigned int state) { | |
| 499 observer_->OnMenuItemActivated(engine_id_, name); | |
| 500 } | |
| 501 | |
| 502 void InputMethodEngineImpl::OnCandidateClicked(unsigned int index, | |
| 503 unsigned int button, | |
| 504 unsigned int state) { | |
| 505 if (index > candidate_ids_.size()) { | |
| 506 return; | |
| 507 } | |
| 508 | |
| 509 MouseButtonEvent pressed_button; | |
| 510 if (button & input_method::IBusEngineController::MOUSE_BUTTON_1_MASK) { | |
| 511 pressed_button = MOUSE_BUTTON_LEFT; | |
| 512 } else if (button & input_method::IBusEngineController::MOUSE_BUTTON_2_MASK) { | |
| 513 pressed_button = MOUSE_BUTTON_MIDDLE; | |
| 514 } else if (button & input_method::IBusEngineController::MOUSE_BUTTON_3_MASK) { | |
| 515 pressed_button = MOUSE_BUTTON_RIGHT; | |
| 516 } else { | |
| 517 DVLOG(1) << "Unknown button: " << button; | |
| 518 pressed_button = MOUSE_BUTTON_LEFT; | |
| 519 } | |
| 520 | |
| 521 observer_->OnCandidateClicked( | |
| 522 engine_id_, candidate_ids_.at(index), pressed_button); | |
| 523 } | |
| 524 | |
| 525 class InputMethodEngineStub : public InputMethodEngine { | |
| 526 public: | |
| 527 InputMethodEngineStub() : active_(false) {} | |
| 528 ~InputMethodEngineStub() {} | |
| 529 | |
| 530 bool Init(InputMethodEngine::Observer* observer, | |
| 531 const char* engine_name, | |
| 532 const char* extension_id, | |
| 533 const char* engine_id, | |
| 534 const char* description, | |
| 535 const char* language, | |
| 536 const std::vector<std::string>& layouts, | |
| 537 std::string* error) { | |
| 538 DVLOG(1) << "Init"; | |
| 539 return true; | |
| 540 } | |
| 541 | |
| 542 virtual bool SetComposition(int context_id, | |
| 543 const char* text, int selection_start, | |
| 544 int selection_end, int cursor, | |
| 545 const std::vector<SegmentInfo>& segments, | |
| 546 std::string* error) { | |
| 547 DVLOG(1) << "SetComposition"; | |
| 548 return true; | |
| 549 } | |
| 550 | |
| 551 virtual bool ClearComposition(int context_id, std::string* error) { | |
| 552 DVLOG(1) << "ClearComposition"; | |
| 553 return true; | |
| 554 } | |
| 555 | |
| 556 virtual bool CommitText(int context_id, | |
| 557 const char* text, std::string* error) { | |
| 558 DVLOG(1) << "CommitText"; | |
| 559 return true; | |
| 560 } | |
| 561 | |
| 562 virtual bool SetCandidateWindowVisible(bool visible, std::string* error) { | |
| 563 DVLOG(1) << "SetCandidateWindowVisible"; | |
| 564 return true; | |
| 565 } | |
| 566 | |
| 567 virtual void SetCandidateWindowCursorVisible(bool visible) { | |
| 568 DVLOG(1) << "SetCandidateWindowCursorVisible"; | |
| 569 } | |
| 570 | |
| 571 virtual void SetCandidateWindowVertical(bool vertical) { | |
| 572 DVLOG(1) << "SetCandidateWindowVertical"; | |
| 573 } | |
| 574 | |
| 575 virtual void SetCandidateWindowPageSize(int size) { | |
| 576 DVLOG(1) << "SetCandidateWindowPageSize"; | |
| 577 } | |
| 578 | |
| 579 virtual void SetCandidateWindowAuxText(const char* text) { | |
| 580 DVLOG(1) << "SetCandidateWindowAuxText"; | |
| 581 } | |
| 582 | |
| 583 virtual void SetCandidateWindowAuxTextVisible(bool visible) { | |
| 584 DVLOG(1) << "SetCandidateWindowAuxTextVisible"; | |
| 585 } | |
| 586 | |
| 587 virtual bool SetCandidates(int context_id, | |
| 588 const std::vector<Candidate>& candidates, | |
| 589 std::string* error) { | |
| 590 DVLOG(1) << "SetCandidates"; | |
| 591 return true; | |
| 592 } | |
| 593 | |
| 594 virtual bool SetCursorPosition(int context_id, int candidate_id, | |
| 595 std::string* error) { | |
| 596 DVLOG(1) << "SetCursorPosition"; | |
| 597 return true; | |
| 598 } | |
| 599 | |
| 600 virtual bool SetMenuItems(const std::vector<MenuItem>& items) { | |
| 601 DVLOG(1) << "SetMenuItems"; | |
| 602 return true; | |
| 603 } | |
| 604 | |
| 605 virtual bool UpdateMenuItems(const std::vector<MenuItem>& items) { | |
| 606 DVLOG(1) << "UpdateMenuItems"; | |
| 607 return true; | |
| 608 } | |
| 609 | |
| 610 virtual bool IsActive() const { | |
| 611 DVLOG(1) << "IsActive"; | |
| 612 return active_; | |
| 613 } | |
| 614 | |
| 615 virtual void KeyEventDone(input_method::KeyEventHandle* key_data, | |
| 616 bool handled) { | |
| 617 } | |
| 618 | |
| 619 private: | |
| 620 // True when this IME is active, false if deactive. | |
| 621 bool active_; | |
| 622 | |
| 623 // User specified id of this IME. | |
| 624 std::string engine_id_; | |
| 625 }; | |
| 626 | |
| 627 InputMethodEngine* InputMethodEngine::CreateEngine( | 35 InputMethodEngine* InputMethodEngine::CreateEngine( |
| 628 InputMethodEngine::Observer* observer, | 36 InputMethodEngine::Observer* observer, |
| 629 const char* engine_name, | 37 const char* engine_name, |
| 630 const char* extension_id, | 38 const char* extension_id, |
| 631 const char* engine_id, | 39 const char* engine_id, |
| 632 const char* description, | 40 const char* description, |
| 633 const char* language, | 41 const char* language, |
| 634 const std::vector<std::string>& layouts, | 42 const std::vector<std::string>& layouts, |
| 635 std::string* error) { | 43 std::string* error) { |
| 636 | 44 |
| 637 #if defined(HAVE_IBUS) | 45 InputMethodEngineIBus* engine = new InputMethodEngineIBus(); |
| 638 InputMethodEngineImpl* new_engine = new InputMethodEngineImpl(); | 46 engine->Initialize(observer, |
| 639 #else | 47 engine_name, |
| 640 InputMethodEngineStub* new_engine = new InputMethodEngineStub(); | 48 extension_id, |
| 641 #endif | 49 engine_id, |
| 642 | 50 description, |
| 643 if (!new_engine->Init(observer, engine_name, extension_id, engine_id, | 51 language, |
| 644 description, language, layouts, error)) { | 52 layouts, |
| 645 DVLOG(1) << "Init() failed."; | 53 error); |
| 646 delete new_engine; | 54 return engine; |
| 647 new_engine = NULL; | |
| 648 } | |
| 649 | |
| 650 return new_engine; | |
| 651 } | 55 } |
| 652 | 56 |
| 653 } // namespace chromeos | 57 } // namespace chromeos |
| OLD | NEW |