Chromium Code Reviews| 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_ibus.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_engine_ibus.h" |
| 6 | 6 |
| 7 #define XK_MISCELLANY | 7 #define XK_MISCELLANY |
| 8 #include <X11/keysymdef.h> | 8 #include <X11/keysymdef.h> |
| 9 #include <map> | 9 #include <map> |
| 10 | 10 |
| 11 #include "base/bind.h" | |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "chromeos/dbus/dbus_thread_manager.h" | 17 #include "chromeos/dbus/dbus_thread_manager.h" |
| 17 #include "chromeos/dbus/ibus/ibus_engine_service.h" | |
| 18 #include "chromeos/dbus/ibus/ibus_text.h" | 18 #include "chromeos/dbus/ibus/ibus_text.h" |
| 19 #include "chromeos/ime/candidate_window.h" | 19 #include "chromeos/ime/candidate_window.h" |
| 20 #include "chromeos/ime/component_extension_ime_manager.h" | 20 #include "chromeos/ime/component_extension_ime_manager.h" |
| 21 #include "chromeos/ime/extension_ime_util.h" | 21 #include "chromeos/ime/extension_ime_util.h" |
| 22 #include "chromeos/ime/ibus_keymap.h" | 22 #include "chromeos/ime/ibus_keymap.h" |
| 23 #include "chromeos/ime/input_method_manager.h" | 23 #include "chromeos/ime/input_method_manager.h" |
| 24 #include "dbus/object_path.h" | 24 #include "dbus/object_path.h" |
| 25 | 25 |
| 26 namespace chromeos { | 26 namespace chromeos { |
| 27 const char* kErrorNotActive = "IME is not active"; | 27 const char* kErrorNotActive = "IME is not active"; |
| 28 const char* kErrorWrongContext = "Context is not active"; | 28 const char* kErrorWrongContext = "Context is not active"; |
| 29 const char* kCandidateNotFound = "Candidate not found"; | 29 const char* kCandidateNotFound = "Candidate not found"; |
| 30 const char* kEngineBusPrefix = "org.freedesktop.IBus."; | 30 const char* kEngineBusPrefix = "org.freedesktop.IBus."; |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 const uint32 kIBusAltKeyMask = 1 << 3; | 33 const uint32 kIBusAltKeyMask = 1 << 3; |
| 34 const uint32 kIBusCtrlKeyMask = 1 << 2; | 34 const uint32 kIBusCtrlKeyMask = 1 << 2; |
| 35 const uint32 kIBusShiftKeyMask = 1 << 0; | 35 const uint32 kIBusShiftKeyMask = 1 << 0; |
| 36 const uint32 kIBusCapsLockMask = 1 << 1; | 36 const uint32 kIBusCapsLockMask = 1 << 1; |
| 37 const uint32 kIBusKeyReleaseMask = 1 << 30; | 37 const uint32 kIBusKeyReleaseMask = 1 << 30; |
| 38 | |
| 39 // Notices InputContextHandler that the preedit is changed. | |
|
satorux1
2013/11/15 02:15:50
Notifies?
Hiro Komatsu
2013/11/15 02:32:53
Done.
| |
| 40 void UpdatePreedit(const IBusText& ibus_text, | |
| 41 uint32 cursor_pos, | |
| 42 bool is_visible) { | |
| 43 IBusInputContextHandlerInterface* input_context = | |
| 44 IBusBridge::Get()->GetInputContextHandler(); | |
| 45 if (input_context) | |
| 46 input_context->UpdatePreeditText(ibus_text, cursor_pos, is_visible); | |
| 38 } | 47 } |
| 39 | 48 |
| 49 // Notices CandidateWindowHandler that the auxilary text is changed. | |
|
satorux1
2013/11/15 02:15:50
ditto
Hiro Komatsu
2013/11/15 02:32:53
Done.
| |
| 50 // Auxilary text is usually footer text. | |
| 51 void UpdateAuxiliaryText(const IBusText& ibus_text, bool is_visible) { | |
| 52 IBusPanelCandidateWindowHandlerInterface* candidate_window = | |
| 53 IBusBridge::Get()->GetCandidateWindowHandler(); | |
| 54 if (candidate_window) | |
| 55 candidate_window->UpdateAuxiliaryText(ibus_text.text(), is_visible); | |
| 56 } | |
| 57 | |
| 58 } // namespace | |
| 59 | |
| 40 InputMethodEngineIBus::InputMethodEngineIBus() | 60 InputMethodEngineIBus::InputMethodEngineIBus() |
| 41 : focused_(false), | 61 : focused_(false), |
| 42 active_(false), | 62 active_(false), |
| 43 context_id_(0), | 63 context_id_(0), |
| 44 next_context_id_(1), | 64 next_context_id_(1), |
| 45 is_create_engine_handler_called_(false), | |
| 46 aux_text_(new IBusText()), | 65 aux_text_(new IBusText()), |
| 47 aux_text_visible_(false), | 66 aux_text_visible_(false), |
| 48 observer_(NULL), | 67 observer_(NULL), |
| 49 preedit_text_(new IBusText()), | 68 preedit_text_(new IBusText()), |
| 50 preedit_cursor_(0), | 69 preedit_cursor_(0), |
| 51 candidate_window_(new input_method::CandidateWindow()), | 70 candidate_window_(new input_method::CandidateWindow()), |
| 52 window_visible_(false), | 71 window_visible_(false), |
| 53 weak_ptr_factory_(this) {} | 72 weak_ptr_factory_(this) {} |
| 54 | 73 |
| 55 InputMethodEngineIBus::~InputMethodEngineIBus() { | 74 InputMethodEngineIBus::~InputMethodEngineIBus() { |
| 56 input_method::InputMethodManager::Get()->RemoveInputMethodExtension(ibus_id_); | 75 input_method::InputMethodManager::Get()->RemoveInputMethodExtension(ibus_id_); |
| 57 | 76 |
| 58 // Do not unset engine before removing input method extension, above | 77 // Do not unset engine before removing input method extension, above |
| 59 // function may call reset function of engine object. | 78 // function may call reset function of engine object. |
| 60 if (is_create_engine_handler_called_) { | 79 if (IBusBridge::Get()->GetEngineHandler() == this) |
| 61 GetCurrentService()->UnsetEngine(this); | 80 IBusBridge::Get()->SetEngineHandler(NULL); |
| 62 ibus_engine_service_.reset(); | |
| 63 } | |
| 64 } | 81 } |
| 65 | 82 |
| 66 void InputMethodEngineIBus::Initialize( | 83 void InputMethodEngineIBus::Initialize( |
| 67 InputMethodEngine::Observer* observer, | 84 InputMethodEngine::Observer* observer, |
| 68 const char* engine_name, | 85 const char* engine_name, |
| 69 const char* extension_id, | 86 const char* extension_id, |
| 70 const char* engine_id, | 87 const char* engine_id, |
| 71 const char* description, | 88 const char* description, |
| 72 const std::vector<std::string>& languages, | 89 const std::vector<std::string>& languages, |
| 73 const std::vector<std::string>& layouts, | 90 const std::vector<std::string>& layouts, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 default: | 162 default: |
| 146 continue; | 163 continue; |
| 147 } | 164 } |
| 148 | 165 |
| 149 underline.start_index = segment->start; | 166 underline.start_index = segment->start; |
| 150 underline.end_index = segment->end; | 167 underline.end_index = segment->end; |
| 151 preedit_text_->mutable_underline_attributes()->push_back(underline); | 168 preedit_text_->mutable_underline_attributes()->push_back(underline); |
| 152 } | 169 } |
| 153 | 170 |
| 154 // TODO(nona): Makes focus out mode configuable, if necessary. | 171 // TODO(nona): Makes focus out mode configuable, if necessary. |
| 155 GetCurrentService()->UpdatePreedit( | 172 UpdatePreedit(*preedit_text_, preedit_cursor_, true); |
| 156 *preedit_text_.get(), | |
| 157 preedit_cursor_, | |
| 158 true, | |
| 159 IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT); | |
| 160 return true; | 173 return true; |
| 161 } | 174 } |
| 162 | 175 |
| 163 bool InputMethodEngineIBus::ClearComposition(int context_id, | 176 bool InputMethodEngineIBus::ClearComposition(int context_id, |
| 164 std::string* error) { | 177 std::string* error) { |
| 165 if (!active_) { | 178 if (!active_) { |
| 166 *error = kErrorNotActive; | 179 *error = kErrorNotActive; |
| 167 return false; | 180 return false; |
| 168 } | 181 } |
| 169 if (context_id != context_id_ || context_id_ == -1) { | 182 if (context_id != context_id_ || context_id_ == -1) { |
| 170 *error = kErrorWrongContext; | 183 *error = kErrorWrongContext; |
| 171 return false; | 184 return false; |
| 172 } | 185 } |
| 173 | 186 |
| 174 preedit_cursor_ = 0; | 187 preedit_cursor_ = 0; |
| 175 preedit_text_.reset(new IBusText()); | 188 preedit_text_.reset(new IBusText()); |
| 176 GetCurrentService()->UpdatePreedit( | 189 UpdatePreedit(*preedit_text_, preedit_cursor_, false); |
| 177 *preedit_text_.get(), | |
| 178 0, | |
| 179 false, | |
| 180 IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT); | |
| 181 return true; | 190 return true; |
| 182 } | 191 } |
| 183 | 192 |
| 184 bool InputMethodEngineIBus::CommitText(int context_id, const char* text, | 193 bool InputMethodEngineIBus::CommitText(int context_id, const char* text, |
| 185 std::string* error) { | 194 std::string* error) { |
| 186 if (!active_) { | 195 if (!active_) { |
| 187 // TODO: Commit the text anyways. | 196 // TODO: Commit the text anyways. |
| 188 *error = kErrorNotActive; | 197 *error = kErrorNotActive; |
| 189 return false; | 198 return false; |
| 190 } | 199 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 IBusBridge::Get()->GetCandidateWindowHandler(); | 246 IBusBridge::Get()->GetCandidateWindowHandler(); |
| 238 if (cw_handler) | 247 if (cw_handler) |
| 239 cw_handler->UpdateLookupTable(*candidate_window_, window_visible_); | 248 cw_handler->UpdateLookupTable(*candidate_window_, window_visible_); |
| 240 return true; | 249 return true; |
| 241 } | 250 } |
| 242 | 251 |
| 243 void InputMethodEngineIBus::SetCandidateWindowAuxText(const char* text) { | 252 void InputMethodEngineIBus::SetCandidateWindowAuxText(const char* text) { |
| 244 aux_text_->set_text(text); | 253 aux_text_->set_text(text); |
| 245 if (active_) { | 254 if (active_) { |
| 246 // Should not show auxiliary text if the whole window visibility is false. | 255 // Should not show auxiliary text if the whole window visibility is false. |
| 247 GetCurrentService()->UpdateAuxiliaryText( | 256 UpdateAuxiliaryText(*aux_text_, window_visible_ && aux_text_visible_); |
| 248 *aux_text_.get(), | |
| 249 window_visible_ && aux_text_visible_); | |
| 250 } | 257 } |
| 251 } | 258 } |
| 252 | 259 |
| 253 void InputMethodEngineIBus::SetCandidateWindowAuxTextVisible(bool visible) { | 260 void InputMethodEngineIBus::SetCandidateWindowAuxTextVisible(bool visible) { |
| 254 aux_text_visible_ = visible; | 261 aux_text_visible_ = visible; |
| 255 if (active_) { | 262 if (active_) { |
| 256 // Should not show auxiliary text if the whole window visibility is false. | 263 // Should not show auxiliary text if the whole window visibility is false. |
| 257 GetCurrentService()->UpdateAuxiliaryText( | 264 UpdateAuxiliaryText(*aux_text_, window_visible_ && aux_text_visible_); |
| 258 *aux_text_.get(), | |
| 259 window_visible_ && aux_text_visible_); | |
| 260 } | 265 } |
| 261 } | 266 } |
| 262 | 267 |
| 263 bool InputMethodEngineIBus::SetCandidates( | 268 bool InputMethodEngineIBus::SetCandidates( |
| 264 int context_id, | 269 int context_id, |
| 265 const std::vector<Candidate>& candidates, | 270 const std::vector<Candidate>& candidates, |
| 266 std::string* error) { | 271 std::string* error) { |
| 267 if (!active_) { | 272 if (!active_) { |
| 268 *error = kErrorNotActive; | 273 *error = kErrorNotActive; |
| 269 return false; | 274 return false; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 } | 379 } |
| 375 if (context_id != context_id_ || context_id_ == -1) { | 380 if (context_id != context_id_ || context_id_ == -1) { |
| 376 *error = kErrorWrongContext; | 381 *error = kErrorWrongContext; |
| 377 return false; | 382 return false; |
| 378 } | 383 } |
| 379 | 384 |
| 380 if (offset < 0 && static_cast<size_t>(-1 * offset) != size_t(number_of_chars)) | 385 if (offset < 0 && static_cast<size_t>(-1 * offset) != size_t(number_of_chars)) |
| 381 return false; // Currently we can only support preceding text. | 386 return false; // Currently we can only support preceding text. |
| 382 | 387 |
| 383 // TODO(nona): Return false if there is ongoing composition. | 388 // TODO(nona): Return false if there is ongoing composition. |
| 384 GetCurrentService()->DeleteSurroundingText(offset, number_of_chars); | 389 |
| 390 IBusInputContextHandlerInterface* input_context = | |
| 391 IBusBridge::Get()->GetInputContextHandler(); | |
| 392 if (input_context) | |
| 393 input_context->DeleteSurroundingText(offset, number_of_chars); | |
| 394 | |
| 385 return true; | 395 return true; |
| 386 } | 396 } |
| 387 | 397 |
| 388 void InputMethodEngineIBus::FocusIn(ibus::TextInputType text_input_type) { | 398 void InputMethodEngineIBus::FocusIn(ibus::TextInputType text_input_type) { |
| 389 focused_ = true; | 399 focused_ = true; |
| 390 if (!active_) | 400 if (!active_) |
| 391 return; | 401 return; |
| 392 context_id_ = next_context_id_; | 402 context_id_ = next_context_id_; |
| 393 ++next_context_id_; | 403 ++next_context_id_; |
| 394 | 404 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 424 return; | 434 return; |
| 425 int context_id = context_id_; | 435 int context_id = context_id_; |
| 426 context_id_ = -1; | 436 context_id_ = -1; |
| 427 observer_->OnBlur(context_id); | 437 observer_->OnBlur(context_id); |
| 428 } | 438 } |
| 429 | 439 |
| 430 void InputMethodEngineIBus::Enable() { | 440 void InputMethodEngineIBus::Enable() { |
| 431 active_ = true; | 441 active_ = true; |
| 432 observer_->OnActivate(engine_id_); | 442 observer_->OnActivate(engine_id_); |
| 433 FocusIn(ibus::TEXT_INPUT_TYPE_TEXT); | 443 FocusIn(ibus::TEXT_INPUT_TYPE_TEXT); |
| 434 | |
| 435 // Calls RequireSurroundingText once here to notify ibus-daemon to send | |
| 436 // surrounding text to this engine. | |
| 437 GetCurrentService()->RequireSurroundingText(); | |
| 438 } | 444 } |
| 439 | 445 |
| 440 void InputMethodEngineIBus::Disable() { | 446 void InputMethodEngineIBus::Disable() { |
| 441 active_ = false; | 447 active_ = false; |
| 442 observer_->OnDeactivated(engine_id_); | 448 observer_->OnDeactivated(engine_id_); |
| 443 } | 449 } |
| 444 | 450 |
| 445 void InputMethodEngineIBus::PropertyActivate(const std::string& property_name) { | 451 void InputMethodEngineIBus::PropertyActivate(const std::string& property_name) { |
| 446 observer_->OnMenuItemActivated(engine_id_, property_name); | 452 observer_->OnMenuItemActivated(engine_id_, property_name); |
| 447 } | 453 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 | 521 |
| 516 void InputMethodEngineIBus::SetSurroundingText(const std::string& text, | 522 void InputMethodEngineIBus::SetSurroundingText(const std::string& text, |
| 517 uint32 cursor_pos, | 523 uint32 cursor_pos, |
| 518 uint32 anchor_pos) { | 524 uint32 anchor_pos) { |
| 519 observer_->OnSurroundingTextChanged(engine_id_, | 525 observer_->OnSurroundingTextChanged(engine_id_, |
| 520 text, | 526 text, |
| 521 static_cast<int>(cursor_pos), | 527 static_cast<int>(cursor_pos), |
| 522 static_cast<int>(anchor_pos)); | 528 static_cast<int>(anchor_pos)); |
| 523 } | 529 } |
| 524 | 530 |
| 525 IBusEngineService* InputMethodEngineIBus::GetCurrentService() { | |
| 526 if (!ibus_engine_service_) | |
| 527 ibus_engine_service_.reset(IBusEngineService::Create()); | |
| 528 return ibus_engine_service_.get(); | |
| 529 } | |
| 530 | |
| 531 void InputMethodEngineIBus::MenuItemToProperty( | 531 void InputMethodEngineIBus::MenuItemToProperty( |
| 532 const MenuItem& item, | 532 const MenuItem& item, |
| 533 input_method::InputMethodProperty* property) { | 533 input_method::InputMethodProperty* property) { |
| 534 property->key = item.id; | 534 property->key = item.id; |
| 535 | 535 |
| 536 if (item.modified & MENU_ITEM_MODIFIED_LABEL) { | 536 if (item.modified & MENU_ITEM_MODIFIED_LABEL) { |
| 537 property->label = item.label; | 537 property->label = item.label; |
| 538 } | 538 } |
| 539 if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) { | 539 if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) { |
| 540 // TODO(nona): Implement it. | 540 // TODO(nona): Implement it. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 } | 577 } |
| 578 | 578 |
| 579 void InputMethodEngineIBus::RegisterComponent() { | 579 void InputMethodEngineIBus::RegisterComponent() { |
| 580 IBusBridge::Get()->SetCreateEngineHandler( | 580 IBusBridge::Get()->SetCreateEngineHandler( |
| 581 ibus_id_, | 581 ibus_id_, |
| 582 base::Bind(&InputMethodEngineIBus::CreateEngineHandler, | 582 base::Bind(&InputMethodEngineIBus::CreateEngineHandler, |
| 583 weak_ptr_factory_.GetWeakPtr())); | 583 weak_ptr_factory_.GetWeakPtr())); |
| 584 } | 584 } |
| 585 | 585 |
| 586 void InputMethodEngineIBus::CreateEngineHandler() { | 586 void InputMethodEngineIBus::CreateEngineHandler() { |
| 587 GetCurrentService()->UnsetEngine(this); | 587 IBusBridge::Get()->SetEngineHandler(this); |
| 588 ibus_engine_service_.reset(); | |
| 589 GetCurrentService()->SetEngine(this); | |
| 590 is_create_engine_handler_called_ = true; | |
| 591 } | 588 } |
| 592 | 589 |
| 593 } // namespace chromeos | 590 } // namespace chromeos |
| OLD | NEW |