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 void UpdatePreedit(const IBusText& ibus_text, | |
|
satorux1
2013/11/13 14:22:07
function comment is missing.
Hiro Komatsu
2013/11/14 01:55:24
Done.
| |
| 40 uint32 cursor_pos, | |
| 41 bool is_visible) { | |
| 42 IBusInputContextHandlerInterface* input_context = | |
| 43 IBusBridge::Get()->GetInputContextHandler(); | |
| 44 if (input_context) | |
| 45 input_context->UpdatePreeditText(ibus_text, cursor_pos, is_visible); | |
| 38 } | 46 } |
| 39 | 47 |
| 48 void UpdateAuxiliaryText(const IBusText& ibus_text, bool is_visible) { | |
|
satorux1
2013/11/13 14:22:07
ditto.
Hiro Komatsu
2013/11/14 01:55:24
Done.
| |
| 49 IBusPanelCandidateWindowHandlerInterface* candidate_window = | |
| 50 IBusBridge::Get()->GetCandidateWindowHandler(); | |
| 51 if (candidate_window) | |
| 52 candidate_window->UpdateAuxiliaryText(ibus_text.text(), is_visible); | |
| 53 } | |
| 54 | |
| 55 } // namespace | |
| 56 | |
| 40 InputMethodEngineIBus::InputMethodEngineIBus() | 57 InputMethodEngineIBus::InputMethodEngineIBus() |
| 41 : focused_(false), | 58 : focused_(false), |
| 42 active_(false), | 59 active_(false), |
| 43 context_id_(0), | 60 context_id_(0), |
| 44 next_context_id_(1), | 61 next_context_id_(1), |
| 45 is_create_engine_handler_called_(false), | |
| 46 aux_text_(new IBusText()), | 62 aux_text_(new IBusText()), |
| 47 aux_text_visible_(false), | 63 aux_text_visible_(false), |
| 48 observer_(NULL), | 64 observer_(NULL), |
| 49 preedit_text_(new IBusText()), | 65 preedit_text_(new IBusText()), |
| 50 preedit_cursor_(0), | 66 preedit_cursor_(0), |
| 51 candidate_window_(new input_method::CandidateWindow()), | 67 candidate_window_(new input_method::CandidateWindow()), |
| 52 window_visible_(false), | 68 window_visible_(false), |
| 53 weak_ptr_factory_(this) {} | 69 weak_ptr_factory_(this) {} |
| 54 | 70 |
| 55 InputMethodEngineIBus::~InputMethodEngineIBus() { | 71 InputMethodEngineIBus::~InputMethodEngineIBus() { |
| 56 input_method::InputMethodManager::Get()->RemoveInputMethodExtension(ibus_id_); | 72 input_method::InputMethodManager::Get()->RemoveInputMethodExtension(ibus_id_); |
| 57 | 73 |
| 58 // Do not unset engine before removing input method extension, above | 74 // Do not unset engine before removing input method extension, above |
| 59 // function may call reset function of engine object. | 75 // function may call reset function of engine object. |
| 60 if (is_create_engine_handler_called_) { | 76 if (IBusBridge::Get()->GetEngineHandler() == this) |
| 61 GetCurrentService()->UnsetEngine(this); | 77 IBusBridge::Get()->SetEngineHandler(NULL); |
| 62 ibus_engine_service_.reset(); | |
| 63 } | |
| 64 } | 78 } |
| 65 | 79 |
| 66 void InputMethodEngineIBus::Initialize( | 80 void InputMethodEngineIBus::Initialize( |
| 67 InputMethodEngine::Observer* observer, | 81 InputMethodEngine::Observer* observer, |
| 68 const char* engine_name, | 82 const char* engine_name, |
| 69 const char* extension_id, | 83 const char* extension_id, |
| 70 const char* engine_id, | 84 const char* engine_id, |
| 71 const char* description, | 85 const char* description, |
| 72 const std::vector<std::string>& languages, | 86 const std::vector<std::string>& languages, |
| 73 const std::vector<std::string>& layouts, | 87 const std::vector<std::string>& layouts, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 default: | 159 default: |
| 146 continue; | 160 continue; |
| 147 } | 161 } |
| 148 | 162 |
| 149 underline.start_index = segment->start; | 163 underline.start_index = segment->start; |
| 150 underline.end_index = segment->end; | 164 underline.end_index = segment->end; |
| 151 preedit_text_->mutable_underline_attributes()->push_back(underline); | 165 preedit_text_->mutable_underline_attributes()->push_back(underline); |
| 152 } | 166 } |
| 153 | 167 |
| 154 // TODO(nona): Makes focus out mode configuable, if necessary. | 168 // TODO(nona): Makes focus out mode configuable, if necessary. |
| 155 GetCurrentService()->UpdatePreedit( | 169 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; | 170 return true; |
| 161 } | 171 } |
| 162 | 172 |
| 163 bool InputMethodEngineIBus::ClearComposition(int context_id, | 173 bool InputMethodEngineIBus::ClearComposition(int context_id, |
| 164 std::string* error) { | 174 std::string* error) { |
| 165 if (!active_) { | 175 if (!active_) { |
| 166 *error = kErrorNotActive; | 176 *error = kErrorNotActive; |
| 167 return false; | 177 return false; |
| 168 } | 178 } |
| 169 if (context_id != context_id_ || context_id_ == -1) { | 179 if (context_id != context_id_ || context_id_ == -1) { |
| 170 *error = kErrorWrongContext; | 180 *error = kErrorWrongContext; |
| 171 return false; | 181 return false; |
| 172 } | 182 } |
| 173 | 183 |
| 174 preedit_cursor_ = 0; | 184 preedit_cursor_ = 0; |
| 175 preedit_text_.reset(new IBusText()); | 185 preedit_text_.reset(new IBusText()); |
| 176 GetCurrentService()->UpdatePreedit( | 186 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; | 187 return true; |
| 182 } | 188 } |
| 183 | 189 |
| 184 bool InputMethodEngineIBus::CommitText(int context_id, const char* text, | 190 bool InputMethodEngineIBus::CommitText(int context_id, const char* text, |
| 185 std::string* error) { | 191 std::string* error) { |
| 186 if (!active_) { | 192 if (!active_) { |
| 187 // TODO: Commit the text anyways. | 193 // TODO: Commit the text anyways. |
| 188 *error = kErrorNotActive; | 194 *error = kErrorNotActive; |
| 189 return false; | 195 return false; |
| 190 } | 196 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 IBusBridge::Get()->GetCandidateWindowHandler(); | 243 IBusBridge::Get()->GetCandidateWindowHandler(); |
| 238 if (cw_handler) | 244 if (cw_handler) |
| 239 cw_handler->UpdateLookupTable(*candidate_window_, window_visible_); | 245 cw_handler->UpdateLookupTable(*candidate_window_, window_visible_); |
| 240 return true; | 246 return true; |
| 241 } | 247 } |
| 242 | 248 |
| 243 void InputMethodEngineIBus::SetCandidateWindowAuxText(const char* text) { | 249 void InputMethodEngineIBus::SetCandidateWindowAuxText(const char* text) { |
| 244 aux_text_->set_text(text); | 250 aux_text_->set_text(text); |
| 245 if (active_) { | 251 if (active_) { |
| 246 // Should not show auxiliary text if the whole window visibility is false. | 252 // Should not show auxiliary text if the whole window visibility is false. |
| 247 GetCurrentService()->UpdateAuxiliaryText( | 253 UpdateAuxiliaryText(*aux_text_, window_visible_ && aux_text_visible_); |
| 248 *aux_text_.get(), | |
| 249 window_visible_ && aux_text_visible_); | |
| 250 } | 254 } |
| 251 } | 255 } |
| 252 | 256 |
| 253 void InputMethodEngineIBus::SetCandidateWindowAuxTextVisible(bool visible) { | 257 void InputMethodEngineIBus::SetCandidateWindowAuxTextVisible(bool visible) { |
| 254 aux_text_visible_ = visible; | 258 aux_text_visible_ = visible; |
| 255 if (active_) { | 259 if (active_) { |
| 256 // Should not show auxiliary text if the whole window visibility is false. | 260 // Should not show auxiliary text if the whole window visibility is false. |
| 257 GetCurrentService()->UpdateAuxiliaryText( | 261 UpdateAuxiliaryText(*aux_text_, window_visible_ && aux_text_visible_); |
| 258 *aux_text_.get(), | |
| 259 window_visible_ && aux_text_visible_); | |
| 260 } | 262 } |
| 261 } | 263 } |
| 262 | 264 |
| 263 bool InputMethodEngineIBus::SetCandidates( | 265 bool InputMethodEngineIBus::SetCandidates( |
| 264 int context_id, | 266 int context_id, |
| 265 const std::vector<Candidate>& candidates, | 267 const std::vector<Candidate>& candidates, |
| 266 std::string* error) { | 268 std::string* error) { |
| 267 if (!active_) { | 269 if (!active_) { |
| 268 *error = kErrorNotActive; | 270 *error = kErrorNotActive; |
| 269 return false; | 271 return false; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 } | 376 } |
| 375 if (context_id != context_id_ || context_id_ == -1) { | 377 if (context_id != context_id_ || context_id_ == -1) { |
| 376 *error = kErrorWrongContext; | 378 *error = kErrorWrongContext; |
| 377 return false; | 379 return false; |
| 378 } | 380 } |
| 379 | 381 |
| 380 if (offset < 0 && static_cast<size_t>(-1 * offset) != size_t(number_of_chars)) | 382 if (offset < 0 && static_cast<size_t>(-1 * offset) != size_t(number_of_chars)) |
| 381 return false; // Currently we can only support preceding text. | 383 return false; // Currently we can only support preceding text. |
| 382 | 384 |
| 383 // TODO(nona): Return false if there is ongoing composition. | 385 // TODO(nona): Return false if there is ongoing composition. |
| 384 GetCurrentService()->DeleteSurroundingText(offset, number_of_chars); | 386 |
| 387 IBusInputContextHandlerInterface* input_context = | |
| 388 IBusBridge::Get()->GetInputContextHandler(); | |
| 389 if (input_context) | |
| 390 input_context->DeleteSurroundingText(offset, number_of_chars); | |
| 391 | |
| 385 return true; | 392 return true; |
| 386 } | 393 } |
| 387 | 394 |
| 388 void InputMethodEngineIBus::FocusIn(ibus::TextInputType text_input_type) { | 395 void InputMethodEngineIBus::FocusIn(ibus::TextInputType text_input_type) { |
| 389 focused_ = true; | 396 focused_ = true; |
| 390 if (!active_) | 397 if (!active_) |
| 391 return; | 398 return; |
| 392 context_id_ = next_context_id_; | 399 context_id_ = next_context_id_; |
| 393 ++next_context_id_; | 400 ++next_context_id_; |
| 394 | 401 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 424 return; | 431 return; |
| 425 int context_id = context_id_; | 432 int context_id = context_id_; |
| 426 context_id_ = -1; | 433 context_id_ = -1; |
| 427 observer_->OnBlur(context_id); | 434 observer_->OnBlur(context_id); |
| 428 } | 435 } |
| 429 | 436 |
| 430 void InputMethodEngineIBus::Enable() { | 437 void InputMethodEngineIBus::Enable() { |
| 431 active_ = true; | 438 active_ = true; |
| 432 observer_->OnActivate(engine_id_); | 439 observer_->OnActivate(engine_id_); |
| 433 FocusIn(ibus::TEXT_INPUT_TYPE_TEXT); | 440 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 } | 441 } |
| 439 | 442 |
| 440 void InputMethodEngineIBus::Disable() { | 443 void InputMethodEngineIBus::Disable() { |
| 441 active_ = false; | 444 active_ = false; |
| 442 observer_->OnDeactivated(engine_id_); | 445 observer_->OnDeactivated(engine_id_); |
| 443 } | 446 } |
| 444 | 447 |
| 445 void InputMethodEngineIBus::PropertyActivate(const std::string& property_name) { | 448 void InputMethodEngineIBus::PropertyActivate(const std::string& property_name) { |
| 446 observer_->OnMenuItemActivated(engine_id_, property_name); | 449 observer_->OnMenuItemActivated(engine_id_, property_name); |
| 447 } | 450 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 | 518 |
| 516 void InputMethodEngineIBus::SetSurroundingText(const std::string& text, | 519 void InputMethodEngineIBus::SetSurroundingText(const std::string& text, |
| 517 uint32 cursor_pos, | 520 uint32 cursor_pos, |
| 518 uint32 anchor_pos) { | 521 uint32 anchor_pos) { |
| 519 observer_->OnSurroundingTextChanged(engine_id_, | 522 observer_->OnSurroundingTextChanged(engine_id_, |
| 520 text, | 523 text, |
| 521 static_cast<int>(cursor_pos), | 524 static_cast<int>(cursor_pos), |
| 522 static_cast<int>(anchor_pos)); | 525 static_cast<int>(anchor_pos)); |
| 523 } | 526 } |
| 524 | 527 |
| 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( | 528 void InputMethodEngineIBus::MenuItemToProperty( |
| 532 const MenuItem& item, | 529 const MenuItem& item, |
| 533 input_method::InputMethodProperty* property) { | 530 input_method::InputMethodProperty* property) { |
| 534 property->key = item.id; | 531 property->key = item.id; |
| 535 | 532 |
| 536 if (item.modified & MENU_ITEM_MODIFIED_LABEL) { | 533 if (item.modified & MENU_ITEM_MODIFIED_LABEL) { |
| 537 property->label = item.label; | 534 property->label = item.label; |
| 538 } | 535 } |
| 539 if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) { | 536 if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) { |
| 540 // TODO(nona): Implement it. | 537 // TODO(nona): Implement it. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 } | 574 } |
| 578 | 575 |
| 579 void InputMethodEngineIBus::RegisterComponent() { | 576 void InputMethodEngineIBus::RegisterComponent() { |
| 580 IBusBridge::Get()->SetCreateEngineHandler( | 577 IBusBridge::Get()->SetCreateEngineHandler( |
| 581 ibus_id_, | 578 ibus_id_, |
| 582 base::Bind(&InputMethodEngineIBus::CreateEngineHandler, | 579 base::Bind(&InputMethodEngineIBus::CreateEngineHandler, |
| 583 weak_ptr_factory_.GetWeakPtr())); | 580 weak_ptr_factory_.GetWeakPtr())); |
| 584 } | 581 } |
| 585 | 582 |
| 586 void InputMethodEngineIBus::CreateEngineHandler() { | 583 void InputMethodEngineIBus::CreateEngineHandler() { |
| 587 GetCurrentService()->UnsetEngine(this); | 584 IBusBridge::Get()->SetEngineHandler(this); |
| 588 ibus_engine_service_.reset(); | |
| 589 GetCurrentService()->SetEngine(this); | |
| 590 is_create_engine_handler_called_ = true; | |
| 591 } | 585 } |
| 592 | 586 |
| 593 } // namespace chromeos | 587 } // namespace chromeos |
| OLD | NEW |