| 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/ibus_controller_impl.h" | 5 #include "chrome/browser/chromeos/input_method/ibus_controller_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> // for std::reverse. | 7 #include <algorithm> // for std::reverse. |
| 8 #include <cstdio> | 8 #include <cstdio> |
| 9 #include <cstring> // for std::strcmp. | 9 #include <cstring> // for std::strcmp. |
| 10 #include <set> | 10 #include <set> |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 return true; | 71 return true; |
| 72 } | 72 } |
| 73 return false; | 73 return false; |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Returns IBusInputContext for |input_context_path|. NULL on errors. | 76 // Returns IBusInputContext for |input_context_path|. NULL on errors. |
| 77 IBusInputContext* GetInputContext(const std::string& input_context_path, | 77 IBusInputContext* GetInputContext(const std::string& input_context_path, |
| 78 IBusBus* ibus) { | 78 IBusBus* ibus) { |
| 79 GDBusConnection* connection = ibus_bus_get_connection(ibus); | 79 GDBusConnection* connection = ibus_bus_get_connection(ibus); |
| 80 if (!connection) { | 80 if (!connection) { |
| 81 LOG(ERROR) << "IBusConnection is null"; | 81 DVLOG(1) << "IBusConnection is null"; |
| 82 return NULL; | 82 return NULL; |
| 83 } | 83 } |
| 84 // This function does not issue an IBus IPC. | 84 // This function does not issue an IBus IPC. |
| 85 IBusInputContext* context = ibus_input_context_get_input_context( | 85 IBusInputContext* context = ibus_input_context_get_input_context( |
| 86 input_context_path.c_str(), connection); | 86 input_context_path.c_str(), connection); |
| 87 if (!context) | 87 if (!context) |
| 88 LOG(ERROR) << "IBusInputContext is null: " << input_context_path; | 88 DVLOG(1) << "IBusInputContext is null: " << input_context_path; |
| 89 return context; | 89 return context; |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Returns true if |prop| has children. | 92 // Returns true if |prop| has children. |
| 93 bool PropertyHasChildren(IBusProperty* prop) { | 93 bool PropertyHasChildren(IBusProperty* prop) { |
| 94 return prop && ibus_property_get_sub_props(prop) && | 94 return prop && ibus_property_get_sub_props(prop) && |
| 95 ibus_prop_list_get(ibus_property_get_sub_props(prop), 0); | 95 ibus_prop_list_get(ibus_property_get_sub_props(prop), 0); |
| 96 } | 96 } |
| 97 | 97 |
| 98 // This function is called by and FlattenProperty() and converts IBus | 98 // This function is called by and FlattenProperty() and converts IBus |
| 99 // representation of a property, |ibus_prop|, to our own and push_back the | 99 // representation of a property, |ibus_prop|, to our own and push_back the |
| 100 // result to |out_prop_list|. This function returns true on success, and | 100 // result to |out_prop_list|. This function returns true on success, and |
| 101 // returns false if sanity checks for |ibus_prop| fail. | 101 // returns false if sanity checks for |ibus_prop| fail. |
| 102 bool ConvertProperty(IBusProperty* ibus_prop, | 102 bool ConvertProperty(IBusProperty* ibus_prop, |
| 103 int selection_item_id, | 103 int selection_item_id, |
| 104 InputMethodPropertyList* out_prop_list) { | 104 InputMethodPropertyList* out_prop_list) { |
| 105 DCHECK(ibus_prop); | 105 DCHECK(ibus_prop); |
| 106 DCHECK(out_prop_list); | 106 DCHECK(out_prop_list); |
| 107 | 107 |
| 108 const IBusPropType type = ibus_property_get_prop_type(ibus_prop); | 108 const IBusPropType type = ibus_property_get_prop_type(ibus_prop); |
| 109 const IBusPropState state = ibus_property_get_state(ibus_prop); | 109 const IBusPropState state = ibus_property_get_state(ibus_prop); |
| 110 const IBusText* tooltip = ibus_property_get_tooltip(ibus_prop); | 110 const IBusText* tooltip = ibus_property_get_tooltip(ibus_prop); |
| 111 const IBusText* label = ibus_property_get_label(ibus_prop); | 111 const IBusText* label = ibus_property_get_label(ibus_prop); |
| 112 const gchar* key = ibus_property_get_key(ibus_prop); | 112 const gchar* key = ibus_property_get_key(ibus_prop); |
| 113 DCHECK(key); | 113 DCHECK(key); |
| 114 | 114 |
| 115 // Sanity checks. | 115 // Sanity checks. |
| 116 const bool has_sub_props = PropertyHasChildren(ibus_prop); | 116 const bool has_sub_props = PropertyHasChildren(ibus_prop); |
| 117 if (has_sub_props && (type != PROP_TYPE_MENU)) { | 117 if (has_sub_props && (type != PROP_TYPE_MENU)) { |
| 118 LOG(ERROR) << "The property has sub properties, " | 118 DVLOG(1) << "The property has sub properties, " |
| 119 << "but the type of the property is not PROP_TYPE_MENU"; | 119 << "but the type of the property is not PROP_TYPE_MENU"; |
| 120 return false; | 120 return false; |
| 121 } | 121 } |
| 122 if ((!has_sub_props) && (type == PROP_TYPE_MENU)) { | 122 if ((!has_sub_props) && (type == PROP_TYPE_MENU)) { |
| 123 // This is usually not an error. ibus-daemon sometimes sends empty props. | 123 // This is usually not an error. ibus-daemon sometimes sends empty props. |
| 124 VLOG(1) << "Property list is empty"; | 124 DVLOG(1) << "Property list is empty"; |
| 125 return false; | 125 return false; |
| 126 } | 126 } |
| 127 if (type == PROP_TYPE_SEPARATOR || type == PROP_TYPE_MENU) { | 127 if (type == PROP_TYPE_SEPARATOR || type == PROP_TYPE_MENU) { |
| 128 // This is not an error, but we don't push an item for these types. | 128 // This is not an error, but we don't push an item for these types. |
| 129 return true; | 129 return true; |
| 130 } | 130 } |
| 131 | 131 |
| 132 const bool is_selection_item = (type == PROP_TYPE_RADIO); | 132 const bool is_selection_item = (type == PROP_TYPE_RADIO); |
| 133 selection_item_id = is_selection_item ? | 133 selection_item_id = is_selection_item ? |
| 134 selection_item_id : InputMethodProperty::kInvalidSelectionItemId; | 134 selection_item_id : InputMethodProperty::kInvalidSelectionItemId; |
| 135 | 135 |
| 136 bool is_selection_item_checked = false; | 136 bool is_selection_item_checked = false; |
| 137 if (state == PROP_STATE_INCONSISTENT) { | 137 if (state == PROP_STATE_INCONSISTENT) { |
| 138 LOG(WARNING) << "The property is in PROP_STATE_INCONSISTENT, " | 138 DVLOG(1) << "The property is in PROP_STATE_INCONSISTENT, " |
| 139 << "which is not supported."; | 139 << "which is not supported."; |
| 140 } else if ((!is_selection_item) && (state == PROP_STATE_CHECKED)) { | 140 } else if ((!is_selection_item) && (state == PROP_STATE_CHECKED)) { |
| 141 LOG(WARNING) << "PROP_STATE_CHECKED is meaningful only if the type is " | 141 DVLOG(1) << "PROP_STATE_CHECKED is meaningful only if the type is " |
| 142 << "PROP_TYPE_RADIO."; | 142 << "PROP_TYPE_RADIO."; |
| 143 } else { | 143 } else { |
| 144 is_selection_item_checked = (state == PROP_STATE_CHECKED); | 144 is_selection_item_checked = (state == PROP_STATE_CHECKED); |
| 145 } | 145 } |
| 146 | 146 |
| 147 if (!key) | 147 if (!key) |
| 148 LOG(ERROR) << "key is NULL"; | 148 DVLOG(1) << "key is NULL"; |
| 149 if (tooltip && !tooltip->text) { | 149 if (tooltip && !tooltip->text) { |
| 150 LOG(ERROR) << "tooltip is NOT NULL, but tooltip->text IS NULL: key=" | 150 DVLOG(1) << "tooltip is NOT NULL, but tooltip->text IS NULL: key=" |
| 151 << Or(key, ""); | 151 << Or(key, ""); |
| 152 } | 152 } |
| 153 if (label && !label->text) { | 153 if (label && !label->text) { |
| 154 LOG(ERROR) << "label is NOT NULL, but label->text IS NULL: key=" | 154 DVLOG(1) << "label is NOT NULL, but label->text IS NULL: key=" |
| 155 << Or(key, ""); | 155 << Or(key, ""); |
| 156 } | 156 } |
| 157 | 157 |
| 158 // This label will be localized later. | 158 // This label will be localized later. |
| 159 // See chrome/browser/chromeos/input_method/input_method_util.cc. | 159 // See chrome/browser/chromeos/input_method/input_method_util.cc. |
| 160 std::string label_to_use = (tooltip && tooltip->text) ? tooltip->text : ""; | 160 std::string label_to_use = (tooltip && tooltip->text) ? tooltip->text : ""; |
| 161 if (label_to_use.empty()) { | 161 if (label_to_use.empty()) { |
| 162 // Usually tooltips are more descriptive than labels. | 162 // Usually tooltips are more descriptive than labels. |
| 163 label_to_use = (label && label->text) ? label->text : ""; | 163 label_to_use = (label && label->text) ? label->text : ""; |
| 164 } | 164 } |
| 165 if (label_to_use.empty()) { | 165 if (label_to_use.empty()) { |
| 166 LOG(ERROR) << "The tooltip and label are both empty. Use " << key; | 166 DVLOG(1) << "The tooltip and label are both empty. Use " << key; |
| 167 label_to_use = Or(key, ""); | 167 label_to_use = Or(key, ""); |
| 168 } | 168 } |
| 169 | 169 |
| 170 out_prop_list->push_back(InputMethodProperty(key, | 170 out_prop_list->push_back(InputMethodProperty(key, |
| 171 label_to_use, | 171 label_to_use, |
| 172 is_selection_item, | 172 is_selection_item, |
| 173 is_selection_item_checked, | 173 is_selection_item_checked, |
| 174 selection_item_id)); | 174 selection_item_id)); |
| 175 return true; | 175 return true; |
| 176 } | 176 } |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 NULL /* callback */, | 420 NULL /* callback */, |
| 421 NULL /* user_data */); | 421 NULL /* user_data */); |
| 422 if (ibus_config_) { | 422 if (ibus_config_) { |
| 423 // Release |ibus_config_| unconditionally to make sure next | 423 // Release |ibus_config_| unconditionally to make sure next |
| 424 // IBusConnectionsAreAlive() call will return false. | 424 // IBusConnectionsAreAlive() call will return false. |
| 425 g_object_unref(ibus_config_); | 425 g_object_unref(ibus_config_); |
| 426 ibus_config_ = NULL; | 426 ibus_config_ = NULL; |
| 427 } | 427 } |
| 428 } else if (process_handle_ != base::kNullProcessHandle) { | 428 } else if (process_handle_ != base::kNullProcessHandle) { |
| 429 base::KillProcess(process_handle_, -1, false /* wait */); | 429 base::KillProcess(process_handle_, -1, false /* wait */); |
| 430 LOG(ERROR) << "Killing ibus-daemon. PID=" | 430 DVLOG(1) << "Killing ibus-daemon. PID=" |
| 431 << base::GetProcId(process_handle_); | 431 << base::GetProcId(process_handle_); |
| 432 } else { | 432 } else { |
| 433 // The daemon hasn't been started yet. | 433 // The daemon hasn't been started yet. |
| 434 } | 434 } |
| 435 | 435 |
| 436 process_handle_ = base::kNullProcessHandle; | 436 process_handle_ = base::kNullProcessHandle; |
| 437 should_launch_daemon_ = false; | 437 should_launch_daemon_ = false; |
| 438 return true; | 438 return true; |
| 439 } | 439 } |
| 440 | 440 |
| 441 bool IBusControllerImpl::ChangeInputMethod(const std::string& id) { | 441 bool IBusControllerImpl::ChangeInputMethod(const std::string& id) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 464 // 3. Switch to "xkb:us::eng". No function in this file is called. | 464 // 3. Switch to "xkb:us::eng". No function in this file is called. |
| 465 // 4. Switch back to "mozc". ChangeInputMethod("mozc") is called, but it's | 465 // 4. Switch back to "mozc". ChangeInputMethod("mozc") is called, but it's |
| 466 // basically NOP since ibus-daemon's current IME is already "mozc". | 466 // basically NOP since ibus-daemon's current IME is already "mozc". |
| 467 // IME properties are not sent to Chrome for the same reason. | 467 // IME properties are not sent to Chrome for the same reason. |
| 468 if (id != current_input_method_id_) | 468 if (id != current_input_method_id_) |
| 469 RegisterProperties(NULL, NULL); | 469 RegisterProperties(NULL, NULL); |
| 470 | 470 |
| 471 current_input_method_id_ = id; | 471 current_input_method_id_ = id; |
| 472 | 472 |
| 473 if (!IBusConnectionsAreAlive()) { | 473 if (!IBusConnectionsAreAlive()) { |
| 474 LOG(INFO) << "ChangeInputMethod: IBus connection is not alive (yet)."; | 474 DVLOG(1) << "ChangeInputMethod: IBus connection is not alive (yet)."; |
| 475 // |id| will become usable shortly since Start() has already been called. | 475 // |id| will become usable shortly since Start() has already been called. |
| 476 // Just return true. | 476 // Just return true. |
| 477 } else { | 477 } else { |
| 478 SendChangeInputMethodRequest(id); | 478 SendChangeInputMethodRequest(id); |
| 479 } | 479 } |
| 480 | 480 |
| 481 return true; | 481 return true; |
| 482 } | 482 } |
| 483 | 483 |
| 484 bool IBusControllerImpl::ActivateInputMethodProperty(const std::string& key) { | 484 bool IBusControllerImpl::ActivateInputMethodProperty(const std::string& key) { |
| 485 if (!IBusConnectionsAreAlive()) { | 485 if (!IBusConnectionsAreAlive()) { |
| 486 LOG(ERROR) << "ActivateInputMethodProperty: IBus connection is not alive"; | 486 DVLOG(1) << "ActivateInputMethodProperty: IBus connection is not alive"; |
| 487 return false; | 487 return false; |
| 488 } | 488 } |
| 489 if (current_input_context_path_.empty()) { | 489 if (current_input_context_path_.empty()) { |
| 490 LOG(ERROR) << "Input context is unknown"; | 490 DVLOG(1) << "Input context is unknown"; |
| 491 return false; | 491 return false; |
| 492 } | 492 } |
| 493 | 493 |
| 494 // The third parameter of ibus_input_context_property_activate() has to be | 494 // The third parameter of ibus_input_context_property_activate() has to be |
| 495 // true when the |key| points to a radio button. false otherwise. | 495 // true when the |key| points to a radio button. false otherwise. |
| 496 bool is_radio = true; | 496 bool is_radio = true; |
| 497 size_t i; | 497 size_t i; |
| 498 for (i = 0; i < current_property_list_.size(); ++i) { | 498 for (i = 0; i < current_property_list_.size(); ++i) { |
| 499 if (current_property_list_[i].key == key) { | 499 if (current_property_list_[i].key == key) { |
| 500 is_radio = current_property_list_[i].is_selection_item; | 500 is_radio = current_property_list_[i].is_selection_item; |
| 501 break; | 501 break; |
| 502 } | 502 } |
| 503 } | 503 } |
| 504 if (i == current_property_list_.size()) { | 504 if (i == current_property_list_.size()) { |
| 505 LOG(ERROR) << "ActivateInputMethodProperty: unknown key: " << key; | 505 DVLOG(1) << "ActivateInputMethodProperty: unknown key: " << key; |
| 506 return false; | 506 return false; |
| 507 } | 507 } |
| 508 | 508 |
| 509 IBusInputContext* context = | 509 IBusInputContext* context = |
| 510 GetInputContext(current_input_context_path_, ibus_); | 510 GetInputContext(current_input_context_path_, ibus_); |
| 511 if (!context) | 511 if (!context) |
| 512 return false; | 512 return false; |
| 513 | 513 |
| 514 // Activate the property *asynchronously*. | 514 // Activate the property *asynchronously*. |
| 515 ibus_input_context_property_activate(context, key.c_str(), is_radio); | 515 ibus_input_context_property_activate(context, key.c_str(), is_radio); |
| 516 | 516 |
| 517 // We don't have to call ibus_proxy_destroy(context) explicitly here, | 517 // We don't have to call ibus_proxy_destroy(context) explicitly here, |
| 518 // i.e. we can just call g_object_unref(context), since g_object_unref can | 518 // i.e. we can just call g_object_unref(context), since g_object_unref can |
| 519 // trigger both dispose, which is overridden by src/ibusproxy.c, and | 519 // trigger both dispose, which is overridden by src/ibusproxy.c, and |
| 520 // finalize functions. For details, see | 520 // finalize functions. For details, see |
| 521 // http://library.gnome.org/devel/gobject/stable/gobject-memory.html | 521 // http://library.gnome.org/devel/gobject/stable/gobject-memory.html |
| 522 g_object_unref(context); | 522 g_object_unref(context); |
| 523 | 523 |
| 524 return true; | 524 return true; |
| 525 } | 525 } |
| 526 | 526 |
| 527 #if defined(USE_VIRTUAL_KEYBOARD) | 527 #if defined(USE_VIRTUAL_KEYBOARD) |
| 528 // IBusController override. | 528 // IBusController override. |
| 529 void IBusControllerImpl::SendHandwritingStroke( | 529 void IBusControllerImpl::SendHandwritingStroke( |
| 530 const HandwritingStroke& stroke) { | 530 const HandwritingStroke& stroke) { |
| 531 if (stroke.size() < 2) { | 531 if (stroke.size() < 2) { |
| 532 LOG(WARNING) << "Empty stroke data or a single dot is passed."; | 532 DVLOG(1) << "Empty stroke data or a single dot is passed."; |
| 533 return; | 533 return; |
| 534 } | 534 } |
| 535 | 535 |
| 536 IBusInputContext* context = | 536 IBusInputContext* context = |
| 537 GetInputContext(current_input_context_path_, ibus_); | 537 GetInputContext(current_input_context_path_, ibus_); |
| 538 if (!context) | 538 if (!context) |
| 539 return; | 539 return; |
| 540 | 540 |
| 541 const size_t raw_stroke_size = stroke.size() * 2; | 541 const size_t raw_stroke_size = stroke.size() * 2; |
| 542 scoped_array<double> raw_stroke(new double[raw_stroke_size]); | 542 scoped_array<double> raw_stroke(new double[raw_stroke_size]); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 563 bool IBusControllerImpl::IBusConnectionsAreAlive() { | 563 bool IBusControllerImpl::IBusConnectionsAreAlive() { |
| 564 return (process_handle_ != base::kNullProcessHandle) && | 564 return (process_handle_ != base::kNullProcessHandle) && |
| 565 ibus_ && ibus_bus_is_connected(ibus_) && ibus_config_; | 565 ibus_ && ibus_bus_is_connected(ibus_) && ibus_config_; |
| 566 } | 566 } |
| 567 | 567 |
| 568 void IBusControllerImpl::MaybeRestoreConnections() { | 568 void IBusControllerImpl::MaybeRestoreConnections() { |
| 569 if (IBusConnectionsAreAlive()) | 569 if (IBusConnectionsAreAlive()) |
| 570 return; | 570 return; |
| 571 MaybeRestoreIBusConfig(); | 571 MaybeRestoreIBusConfig(); |
| 572 if (IBusConnectionsAreAlive()) { | 572 if (IBusConnectionsAreAlive()) { |
| 573 LOG(INFO) << "ibus-daemon and ibus-memconf processes are ready."; | 573 DVLOG(1) << "ibus-daemon and ibus-memconf processes are ready."; |
| 574 ConnectPanelServiceSignals(); | 574 ConnectPanelServiceSignals(); |
| 575 SendAllInputMethodConfigs(); | 575 SendAllInputMethodConfigs(); |
| 576 if (!current_input_method_id_.empty()) | 576 if (!current_input_method_id_.empty()) |
| 577 SendChangeInputMethodRequest(current_input_method_id_); | 577 SendChangeInputMethodRequest(current_input_method_id_); |
| 578 } | 578 } |
| 579 } | 579 } |
| 580 | 580 |
| 581 void IBusControllerImpl::MaybeInitializeIBusBus() { | 581 void IBusControllerImpl::MaybeInitializeIBusBus() { |
| 582 if (ibus_) | 582 if (ibus_) |
| 583 return; | 583 return; |
| 584 | 584 |
| 585 ibus_init(); | 585 ibus_init(); |
| 586 // Establish IBus connection between ibus-daemon to change the current input | 586 // Establish IBus connection between ibus-daemon to change the current input |
| 587 // method engine, properties, and so on. | 587 // method engine, properties, and so on. |
| 588 ibus_ = ibus_bus_new(); | 588 ibus_ = ibus_bus_new(); |
| 589 DCHECK(ibus_); | 589 DCHECK(ibus_); |
| 590 | 590 |
| 591 // Register callback functions for IBusBus signals. | 591 // Register callback functions for IBusBus signals. |
| 592 ConnectBusSignals(); | 592 ConnectBusSignals(); |
| 593 | 593 |
| 594 // Ask libibus to watch the NameOwnerChanged signal *asynchronously*. | 594 // Ask libibus to watch the NameOwnerChanged signal *asynchronously*. |
| 595 ibus_bus_set_watch_dbus_signal(ibus_, TRUE); | 595 ibus_bus_set_watch_dbus_signal(ibus_, TRUE); |
| 596 | 596 |
| 597 if (ibus_bus_is_connected(ibus_)) { | 597 if (ibus_bus_is_connected(ibus_)) { |
| 598 LOG(ERROR) << "IBus connection is ready: ibus-daemon is already running?"; | 598 DVLOG(1) << "IBus connection is ready: ibus-daemon is already running?"; |
| 599 BusConnected(ibus_); | 599 BusConnected(ibus_); |
| 600 } | 600 } |
| 601 } | 601 } |
| 602 | 602 |
| 603 void IBusControllerImpl::MaybeRestoreIBusConfig() { | 603 void IBusControllerImpl::MaybeRestoreIBusConfig() { |
| 604 if (!ibus_) | 604 if (!ibus_) |
| 605 return; | 605 return; |
| 606 | 606 |
| 607 // Destroy the current |ibus_config_| object. No-op if it's NULL. | 607 // Destroy the current |ibus_config_| object. No-op if it's NULL. |
| 608 MaybeDestroyIBusConfig(); | 608 MaybeDestroyIBusConfig(); |
| 609 | 609 |
| 610 if (ibus_config_) | 610 if (ibus_config_) |
| 611 return; | 611 return; |
| 612 | 612 |
| 613 GDBusConnection* ibus_connection = ibus_bus_get_connection(ibus_); | 613 GDBusConnection* ibus_connection = ibus_bus_get_connection(ibus_); |
| 614 if (!ibus_connection) { | 614 if (!ibus_connection) { |
| 615 VLOG(1) << "Couldn't create an ibus config object since " | 615 DVLOG(1) << "Couldn't create an ibus config object since " |
| 616 << "IBus connection is not ready."; | 616 << "IBus connection is not ready."; |
| 617 return; | 617 return; |
| 618 } | 618 } |
| 619 | 619 |
| 620 const gboolean disconnected | 620 const gboolean disconnected |
| 621 = g_dbus_connection_is_closed(ibus_connection); | 621 = g_dbus_connection_is_closed(ibus_connection); |
| 622 if (disconnected) { | 622 if (disconnected) { |
| 623 // |ibus_| object is not NULL, but the connection between ibus-daemon | 623 // |ibus_| object is not NULL, but the connection between ibus-daemon |
| 624 // is not yet established. In this case, we don't create |ibus_config_| | 624 // is not yet established. In this case, we don't create |ibus_config_| |
| 625 // object. | 625 // object. |
| 626 LOG(ERROR) << "Couldn't create an ibus config object since " | 626 DVLOG(1) << "Couldn't create an ibus config object since " |
| 627 << "IBus connection is closed."; | 627 << "IBus connection is closed."; |
| 628 return; | 628 return; |
| 629 } | 629 } |
| 630 // If memconf is not successfully started yet, ibus_config_new() will | 630 // If memconf is not successfully started yet, ibus_config_new() will |
| 631 // return NULL. Otherwise, it returns a transfer-none and non-floating | 631 // return NULL. Otherwise, it returns a transfer-none and non-floating |
| 632 // object. ibus_config_new() sometimes issues a D-Bus *synchronous* IPC | 632 // object. ibus_config_new() sometimes issues a D-Bus *synchronous* IPC |
| 633 // to check if the org.freedesktop.IBus.Config service is available. | 633 // to check if the org.freedesktop.IBus.Config service is available. |
| 634 ibus_config_ = ibus_config_new(ibus_connection, | 634 ibus_config_ = ibus_config_new(ibus_connection, |
| 635 NULL /* do not cancel the operation */, | 635 NULL /* do not cancel the operation */, |
| 636 NULL /* do not get error information */); | 636 NULL /* do not get error information */); |
| 637 if (!ibus_config_) { | 637 if (!ibus_config_) { |
| 638 LOG(ERROR) << "ibus_config_new() failed. ibus-memconf is not ready?"; | 638 DVLOG(1) << "ibus_config_new() failed. ibus-memconf is not ready?"; |
| 639 return; | 639 return; |
| 640 } | 640 } |
| 641 | 641 |
| 642 // TODO(yusukes): g_object_weak_ref might be better since it allows | 642 // TODO(yusukes): g_object_weak_ref might be better since it allows |
| 643 // libcros to detect the delivery of the "destroy" glib signal the | 643 // libcros to detect the delivery of the "destroy" glib signal the |
| 644 // |ibus_config_| object. | 644 // |ibus_config_| object. |
| 645 g_object_ref(ibus_config_); | 645 g_object_ref(ibus_config_); |
| 646 VLOG(1) << "ibus_config_ is ready."; | 646 DVLOG(1) << "ibus_config_ is ready."; |
| 647 } | 647 } |
| 648 | 648 |
| 649 void IBusControllerImpl::MaybeDestroyIBusConfig() { | 649 void IBusControllerImpl::MaybeDestroyIBusConfig() { |
| 650 if (!ibus_) { | 650 if (!ibus_) { |
| 651 LOG(ERROR) << "MaybeDestroyIBusConfig: ibus_ is NULL"; | 651 DVLOG(1) << "MaybeDestroyIBusConfig: ibus_ is NULL"; |
| 652 return; | 652 return; |
| 653 } | 653 } |
| 654 if (ibus_config_ && !ibus_bus_is_connected(ibus_)) { | 654 if (ibus_config_ && !ibus_bus_is_connected(ibus_)) { |
| 655 g_object_unref(ibus_config_); | 655 g_object_unref(ibus_config_); |
| 656 ibus_config_ = NULL; | 656 ibus_config_ = NULL; |
| 657 } | 657 } |
| 658 } | 658 } |
| 659 | 659 |
| 660 void IBusControllerImpl::SendChangeInputMethodRequest(const std::string& id) { | 660 void IBusControllerImpl::SendChangeInputMethodRequest(const std::string& id) { |
| 661 // Change the global engine *asynchronously*. | 661 // Change the global engine *asynchronously*. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 for (size_t i = 0; i < size; ++i) { | 703 for (size_t i = 0; i < size; ++i) { |
| 704 g_variant_builder_add(&variant_builder, | 704 g_variant_builder_add(&variant_builder, |
| 705 "s", | 705 "s", |
| 706 value.string_list_value[i].c_str()); | 706 value.string_list_value[i].c_str()); |
| 707 } | 707 } |
| 708 variant = g_variant_builder_end(&variant_builder); | 708 variant = g_variant_builder_end(&variant_builder); |
| 709 break; | 709 break; |
| 710 } | 710 } |
| 711 | 711 |
| 712 if (!variant) { | 712 if (!variant) { |
| 713 LOG(ERROR) << "SendInputMethodConfig: unknown value.type"; | 713 DVLOG(1) << "SendInputMethodConfig: unknown value.type"; |
| 714 return false; | 714 return false; |
| 715 } | 715 } |
| 716 DCHECK(g_variant_is_floating(variant)); | 716 DCHECK(g_variant_is_floating(variant)); |
| 717 DCHECK(ibus_config_); | 717 DCHECK(ibus_config_); |
| 718 | 718 |
| 719 // Set an ibus configuration value *asynchronously*. | 719 // Set an ibus configuration value *asynchronously*. |
| 720 ibus_config_set_value_async(ibus_config_, | 720 ibus_config_set_value_async(ibus_config_, |
| 721 key.first.c_str(), | 721 key.first.c_str(), |
| 722 key.second.c_str(), | 722 key.second.c_str(), |
| 723 variant, | 723 variant, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 this); | 755 this); |
| 756 } | 756 } |
| 757 | 757 |
| 758 void IBusControllerImpl::ConnectPanelServiceSignals() { | 758 void IBusControllerImpl::ConnectPanelServiceSignals() { |
| 759 if (!ibus_) | 759 if (!ibus_) |
| 760 return; | 760 return; |
| 761 | 761 |
| 762 IBusPanelService* ibus_panel_service = IBUS_PANEL_SERVICE( | 762 IBusPanelService* ibus_panel_service = IBUS_PANEL_SERVICE( |
| 763 g_object_get_data(G_OBJECT(ibus_), kPanelObjectKey)); | 763 g_object_get_data(G_OBJECT(ibus_), kPanelObjectKey)); |
| 764 if (!ibus_panel_service) { | 764 if (!ibus_panel_service) { |
| 765 LOG(ERROR) << "IBusPanelService is NOT available."; | 765 DVLOG(1) << "IBusPanelService is NOT available."; |
| 766 return; | 766 return; |
| 767 } | 767 } |
| 768 // We don't _ref() or _weak_ref() the panel service object, since we're not | 768 // We don't _ref() or _weak_ref() the panel service object, since we're not |
| 769 // interested in the life time of the object. | 769 // interested in the life time of the object. |
| 770 | 770 |
| 771 g_signal_connect(ibus_panel_service, | 771 g_signal_connect(ibus_panel_service, |
| 772 "focus-in", | 772 "focus-in", |
| 773 G_CALLBACK(FocusInThunk), | 773 G_CALLBACK(FocusInThunk), |
| 774 this); | 774 this); |
| 775 g_signal_connect(ibus_panel_service, | 775 g_signal_connect(ibus_panel_service, |
| 776 "register-properties", | 776 "register-properties", |
| 777 G_CALLBACK(RegisterPropertiesThunk), | 777 G_CALLBACK(RegisterPropertiesThunk), |
| 778 this); | 778 this); |
| 779 g_signal_connect(ibus_panel_service, | 779 g_signal_connect(ibus_panel_service, |
| 780 "update-property", | 780 "update-property", |
| 781 G_CALLBACK(UpdatePropertyThunk), | 781 G_CALLBACK(UpdatePropertyThunk), |
| 782 this); | 782 this); |
| 783 } | 783 } |
| 784 | 784 |
| 785 void IBusControllerImpl::BusConnected(IBusBus* bus) { | 785 void IBusControllerImpl::BusConnected(IBusBus* bus) { |
| 786 LOG(INFO) << "IBus connection is established."; | 786 DVLOG(1) << "IBus connection is established."; |
| 787 MaybeRestoreConnections(); | 787 MaybeRestoreConnections(); |
| 788 } | 788 } |
| 789 | 789 |
| 790 void IBusControllerImpl::BusDisconnected(IBusBus* bus) { | 790 void IBusControllerImpl::BusDisconnected(IBusBus* bus) { |
| 791 LOG(INFO) << "IBus connection is terminated."; | 791 DVLOG(1) << "IBus connection is terminated."; |
| 792 // ibus-daemon might be terminated. Since |ibus_| object will automatically | 792 // ibus-daemon might be terminated. Since |ibus_| object will automatically |
| 793 // connect to the daemon if it restarts, we don't have to set NULL on ibus_. | 793 // connect to the daemon if it restarts, we don't have to set NULL on ibus_. |
| 794 // Call MaybeDestroyIBusConfig() to set |ibus_config_| to NULL temporarily. | 794 // Call MaybeDestroyIBusConfig() to set |ibus_config_| to NULL temporarily. |
| 795 MaybeDestroyIBusConfig(); | 795 MaybeDestroyIBusConfig(); |
| 796 } | 796 } |
| 797 | 797 |
| 798 void IBusControllerImpl::BusNameOwnerChanged(IBusBus* bus, | 798 void IBusControllerImpl::BusNameOwnerChanged(IBusBus* bus, |
| 799 const gchar* name, | 799 const gchar* name, |
| 800 const gchar* old_name, | 800 const gchar* old_name, |
| 801 const gchar* new_name) { | 801 const gchar* new_name) { |
| 802 DCHECK(name); | 802 DCHECK(name); |
| 803 DCHECK(old_name); | 803 DCHECK(old_name); |
| 804 DCHECK(new_name); | 804 DCHECK(new_name); |
| 805 | 805 |
| 806 if (name != std::string("org.freedesktop.IBus.Config")) { | 806 if (name != std::string("org.freedesktop.IBus.Config")) { |
| 807 // Not a signal for ibus-memconf. | 807 // Not a signal for ibus-memconf. |
| 808 return; | 808 return; |
| 809 } | 809 } |
| 810 | 810 |
| 811 const std::string empty_string; | 811 const std::string empty_string; |
| 812 if (old_name != empty_string || new_name == empty_string) { | 812 if (old_name != empty_string || new_name == empty_string) { |
| 813 // ibus-memconf died? | 813 // ibus-memconf died? |
| 814 LOG(WARNING) << "Unexpected name owner change: name=" << name | 814 DVLOG(1) << "Unexpected name owner change: name=" << name |
| 815 << ", old_name=" << old_name << ", new_name=" << new_name; | 815 << ", old_name=" << old_name << ", new_name=" << new_name; |
| 816 // TODO(yusukes): it might be nice to set |ibus_config_| to NULL and call | 816 // TODO(yusukes): it might be nice to set |ibus_config_| to NULL and call |
| 817 // a new callback function like OnDisconnect() here to allow Chrome to | 817 // a new callback function like OnDisconnect() here to allow Chrome to |
| 818 // recover all input method configurations when ibus-memconf is | 818 // recover all input method configurations when ibus-memconf is |
| 819 // automatically restarted by ibus-daemon. Though ibus-memconf is pretty | 819 // automatically restarted by ibus-daemon. Though ibus-memconf is pretty |
| 820 // stable and unlikely crashes. | 820 // stable and unlikely crashes. |
| 821 return; | 821 return; |
| 822 } | 822 } |
| 823 VLOG(1) << "IBus config daemon is started. Recovering ibus_config_"; | 823 DVLOG(1) << "IBus config daemon is started. Recovering ibus_config_"; |
| 824 | 824 |
| 825 // Try to recover |ibus_config_|. If the |ibus_config_| object is | 825 // Try to recover |ibus_config_|. If the |ibus_config_| object is |
| 826 // successfully created, |OnConnectionChange| will be called to | 826 // successfully created, |OnConnectionChange| will be called to |
| 827 // notify Chrome that IBus is ready. | 827 // notify Chrome that IBus is ready. |
| 828 MaybeRestoreConnections(); | 828 MaybeRestoreConnections(); |
| 829 } | 829 } |
| 830 | 830 |
| 831 void IBusControllerImpl::FocusIn(IBusPanelService* panel, | 831 void IBusControllerImpl::FocusIn(IBusPanelService* panel, |
| 832 const gchar* input_context_path) { | 832 const gchar* input_context_path) { |
| 833 if (!input_context_path) | 833 if (!input_context_path) |
| 834 LOG(ERROR) << "NULL context passed"; | 834 DVLOG(1) << "NULL context passed"; |
| 835 else | 835 else |
| 836 VLOG(1) << "FocusIn: " << input_context_path; | 836 DVLOG(1) << "FocusIn: " << input_context_path; |
| 837 // Remember the current ic path. | 837 // Remember the current ic path. |
| 838 current_input_context_path_ = Or(input_context_path, ""); | 838 current_input_context_path_ = Or(input_context_path, ""); |
| 839 } | 839 } |
| 840 | 840 |
| 841 void IBusControllerImpl::RegisterProperties(IBusPanelService* panel, | 841 void IBusControllerImpl::RegisterProperties(IBusPanelService* panel, |
| 842 IBusPropList* ibus_prop_list) { | 842 IBusPropList* ibus_prop_list) { |
| 843 // Note: |panel| can be NULL. See ChangeInputMethod(). | 843 // Note: |panel| can be NULL. See ChangeInputMethod(). |
| 844 VLOG(1) << "RegisterProperties" << (ibus_prop_list ? "" : " (clear)"); | 844 DVLOG(1) << "RegisterProperties" << (ibus_prop_list ? "" : " (clear)"); |
| 845 | 845 |
| 846 current_property_list_.clear(); | 846 current_property_list_.clear(); |
| 847 if (ibus_prop_list) { | 847 if (ibus_prop_list) { |
| 848 // You can call | 848 // You can call |
| 849 // LOG(INFO) << "\n" << PrintPropList(ibus_prop_list, 0); | 849 // DVLOG(1) << "\n" << PrintPropList(ibus_prop_list, 0); |
| 850 // here to dump |ibus_prop_list|. | 850 // here to dump |ibus_prop_list|. |
| 851 if (!FlattenPropertyList(ibus_prop_list, ¤t_property_list_)) { | 851 if (!FlattenPropertyList(ibus_prop_list, ¤t_property_list_)) { |
| 852 // Clear properties on errors. | 852 // Clear properties on errors. |
| 853 current_property_list_.clear(); | 853 current_property_list_.clear(); |
| 854 } | 854 } |
| 855 } | 855 } |
| 856 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); | 856 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); |
| 857 } | 857 } |
| 858 | 858 |
| 859 void IBusControllerImpl::UpdateProperty(IBusPanelService* panel, | 859 void IBusControllerImpl::UpdateProperty(IBusPanelService* panel, |
| 860 IBusProperty* ibus_prop) { | 860 IBusProperty* ibus_prop) { |
| 861 VLOG(1) << "UpdateProperty"; | 861 DVLOG(1) << "UpdateProperty"; |
| 862 DCHECK(ibus_prop); | 862 DCHECK(ibus_prop); |
| 863 | 863 |
| 864 // You can call | 864 // You can call |
| 865 // LOG(INFO) << "\n" << PrintProp(ibus_prop, 0); | 865 // DVLOG(1) << "\n" << PrintProp(ibus_prop, 0); |
| 866 // here to dump |ibus_prop|. | 866 // here to dump |ibus_prop|. |
| 867 | 867 |
| 868 InputMethodPropertyList prop_list; // our representation. | 868 InputMethodPropertyList prop_list; // our representation. |
| 869 if (!FlattenProperty(ibus_prop, &prop_list)) { | 869 if (!FlattenProperty(ibus_prop, &prop_list)) { |
| 870 // Don't update the UI on errors. | 870 // Don't update the UI on errors. |
| 871 LOG(ERROR) << "Malformed properties are detected"; | 871 DVLOG(1) << "Malformed properties are detected"; |
| 872 return; | 872 return; |
| 873 } | 873 } |
| 874 | 874 |
| 875 // Notify the change. | 875 // Notify the change. |
| 876 if (!prop_list.empty()) { | 876 if (!prop_list.empty()) { |
| 877 for (size_t i = 0; i < prop_list.size(); ++i) { | 877 for (size_t i = 0; i < prop_list.size(); ++i) { |
| 878 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); | 878 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); |
| 879 } | 879 } |
| 880 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); | 880 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); |
| 881 } | 881 } |
| 882 } | 882 } |
| 883 | 883 |
| 884 bool IBusControllerImpl::MaybeLaunchIBusDaemon() { | 884 bool IBusControllerImpl::MaybeLaunchIBusDaemon() { |
| 885 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; | 885 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; |
| 886 | 886 |
| 887 if (process_handle_ != base::kNullProcessHandle) { | 887 if (process_handle_ != base::kNullProcessHandle) { |
| 888 LOG(ERROR) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; | 888 DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; |
| 889 return false; | 889 return false; |
| 890 } | 890 } |
| 891 if (!should_launch_daemon_) | 891 if (!should_launch_daemon_) |
| 892 return false; | 892 return false; |
| 893 | 893 |
| 894 // TODO(zork): Send output to /var/log/ibus.log | 894 // TODO(zork): Send output to /var/log/ibus.log |
| 895 const std::string ibus_daemon_command_line = | 895 const std::string ibus_daemon_command_line = |
| 896 base::StringPrintf("%s --panel=disable --cache=none --restart --replace", | 896 base::StringPrintf("%s --panel=disable --cache=none --restart --replace", |
| 897 kIBusDaemonPath); | 897 kIBusDaemonPath); |
| 898 if (!LaunchProcess(ibus_daemon_command_line, | 898 if (!LaunchProcess(ibus_daemon_command_line, |
| 899 &process_handle_, | 899 &process_handle_, |
| 900 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { | 900 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { |
| 901 LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line; | 901 DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; |
| 902 return false; | 902 return false; |
| 903 } | 903 } |
| 904 return true; | 904 return true; |
| 905 } | 905 } |
| 906 | 906 |
| 907 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, | 907 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, |
| 908 base::ProcessHandle* process_handle, | 908 base::ProcessHandle* process_handle, |
| 909 GChildWatchFunc watch_func) { | 909 GChildWatchFunc watch_func) { |
| 910 std::vector<std::string> argv; | 910 std::vector<std::string> argv; |
| 911 base::ProcessHandle handle = base::kNullProcessHandle; | 911 base::ProcessHandle handle = base::kNullProcessHandle; |
| 912 | 912 |
| 913 base::SplitString(command_line, ' ', &argv); | 913 base::SplitString(command_line, ' ', &argv); |
| 914 | 914 |
| 915 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { | 915 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { |
| 916 LOG(ERROR) << "Could not launch: " << command_line; | 916 DVLOG(1) << "Could not launch: " << command_line; |
| 917 return false; | 917 return false; |
| 918 } | 918 } |
| 919 | 919 |
| 920 // g_child_watch_add is necessary to prevent the process from becoming a | 920 // g_child_watch_add is necessary to prevent the process from becoming a |
| 921 // zombie. | 921 // zombie. |
| 922 // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc. | 922 // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc. |
| 923 const base::ProcessId pid = base::GetProcId(handle); | 923 const base::ProcessId pid = base::GetProcId(handle); |
| 924 g_child_watch_add(pid, watch_func, this); | 924 g_child_watch_add(pid, watch_func, this); |
| 925 | 925 |
| 926 *process_handle = handle; | 926 *process_handle = handle; |
| 927 VLOG(1) << command_line << "is started. PID=" << pid; | 927 DVLOG(1) << command_line << "is started. PID=" << pid; |
| 928 return true; | 928 return true; |
| 929 } | 929 } |
| 930 | 930 |
| 931 // static | 931 // static |
| 932 void IBusControllerImpl::SetInputMethodConfigCallback(GObject* source_object, | 932 void IBusControllerImpl::SetInputMethodConfigCallback(GObject* source_object, |
| 933 GAsyncResult* res, | 933 GAsyncResult* res, |
| 934 gpointer user_data) { | 934 gpointer user_data) { |
| 935 IBusConfig* config = IBUS_CONFIG(user_data); | 935 IBusConfig* config = IBUS_CONFIG(user_data); |
| 936 g_return_if_fail(config); | 936 g_return_if_fail(config); |
| 937 | 937 |
| 938 GError* error = NULL; | 938 GError* error = NULL; |
| 939 const gboolean result = | 939 const gboolean result = |
| 940 ibus_config_set_value_async_finish(config, res, &error); | 940 ibus_config_set_value_async_finish(config, res, &error); |
| 941 | 941 |
| 942 if (!result) { | 942 if (!result) { |
| 943 std::string message = "(unknown error)"; | 943 std::string message = "(unknown error)"; |
| 944 if (error && error->message) { | 944 if (error && error->message) { |
| 945 message = error->message; | 945 message = error->message; |
| 946 } | 946 } |
| 947 LOG(ERROR) << "ibus_config_set_value_async failed: " << message; | 947 DVLOG(1) << "ibus_config_set_value_async failed: " << message; |
| 948 } | 948 } |
| 949 | 949 |
| 950 if (error) | 950 if (error) |
| 951 g_error_free(error); | 951 g_error_free(error); |
| 952 g_object_unref(config); | 952 g_object_unref(config); |
| 953 } | 953 } |
| 954 | 954 |
| 955 // static | 955 // static |
| 956 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, | 956 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, |
| 957 gint status, | 957 gint status, |
| 958 IBusControllerImpl* controller) { | 958 IBusControllerImpl* controller) { |
| 959 if (controller->process_handle_ != base::kNullProcessHandle && | 959 if (controller->process_handle_ != base::kNullProcessHandle && |
| 960 base::GetProcId(controller->process_handle_) == pid) { | 960 base::GetProcId(controller->process_handle_) == pid) { |
| 961 controller->process_handle_ = base::kNullProcessHandle; | 961 controller->process_handle_ = base::kNullProcessHandle; |
| 962 } | 962 } |
| 963 // Restart the daemon if needed. | 963 // Restart the daemon if needed. |
| 964 controller->MaybeLaunchIBusDaemon(); | 964 controller->MaybeLaunchIBusDaemon(); |
| 965 } | 965 } |
| 966 #endif // defined(HAVE_IBUS) | 966 #endif // defined(HAVE_IBUS) |
| 967 | 967 |
| 968 // static | 968 // static |
| 969 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( | 969 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( |
| 970 const chromeos::input_method::InputMethodProperty& new_prop, | 970 const chromeos::input_method::InputMethodProperty& new_prop, |
| 971 chromeos::input_method::InputMethodPropertyList* prop_list) { | 971 chromeos::input_method::InputMethodPropertyList* prop_list) { |
| 972 return FindAndUpdateProperty(new_prop, prop_list); | 972 return FindAndUpdateProperty(new_prop, prop_list); |
| 973 } | 973 } |
| 974 | 974 |
| 975 } // namespace input_method | 975 } // namespace input_method |
| 976 } // namespace chromeos | 976 } // namespace chromeos |
| OLD | NEW |