diff options
Diffstat (limited to 'chromium/ui/base/ime/input_method_ibus.cc')
-rw-r--r-- | chromium/ui/base/ime/input_method_ibus.cc | 280 |
1 files changed, 62 insertions, 218 deletions
diff --git a/chromium/ui/base/ime/input_method_ibus.cc b/chromium/ui/base/ime/input_method_ibus.cc index 7c4f803d445..8ff645a2130 100644 --- a/chromium/ui/base/ime/input_method_ibus.cc +++ b/chromium/ui/base/ime/input_method_ibus.cc @@ -23,30 +23,21 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/ibus/ibus_client.h" -#include "chromeos/dbus/ibus/ibus_input_context_client.h" #include "chromeos/dbus/ibus/ibus_text.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" +#include "chromeos/ime/input_method_descriptor.h" +#include "chromeos/ime/input_method_manager.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/rect.h" namespace { const int kIBusReleaseMask = 1 << 30; -const char kClientName[] = "chrome"; -const int kMaxRetryCount = 10; - -// Following capability mask is introduced from -// http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabilite -const uint32 kIBusCapabilityPreeditText = 1U; -const uint32 kIBusCapabilityFocus = 8U; -const uint32 kIBusCapabilitySurroundingText = 32U; XKeyEvent* GetKeyEvent(XEvent* event) { DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); @@ -70,15 +61,15 @@ uint32 IBusStateFromXState(unsigned int state) { Button1Mask | Button2Mask | Button3Mask)); } -chromeos::IBusInputContextClient* GetInputContextClient() { - return chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); -} - // Converts gfx::Rect to ibus::Rect. chromeos::ibus::Rect GfxRectToIBusRect(const gfx::Rect& rect) { return chromeos::ibus::Rect(rect.x(), rect.y(), rect.width(), rect.height()); } +chromeos::IBusEngineHandlerInterface* GetEngine() { + return chromeos::IBusBridge::Get()->GetEngineHandler(); +} + } // namespace namespace ui { @@ -86,33 +77,28 @@ namespace ui { // InputMethodIBus implementation ----------------------------------------- InputMethodIBus::InputMethodIBus( internal::InputMethodDelegate* delegate) - : input_context_state_(INPUT_CONTEXT_STOP), - create_input_context_fail_count_(0), - context_focused_(false), + : context_focused_(false), composing_text_(false), composition_changed_(false), suppress_next_result_(false), current_keyevent_id_(0), + previous_textinput_type_(TEXT_INPUT_TYPE_NONE), weak_ptr_factory_(this) { SetDelegate(delegate); + chromeos::IBusBridge::Get()->SetInputContextHandler(this); - // chromeos::IBusDaemonController is not available in case of some testing, - // e.g. content_browser test can't initialize IBusDaemonController. - DCHECK(!base::chromeos::IsRunningOnChromeOS() || - chromeos::IBusDaemonController::GetInstance()); - - if (chromeos::IBusDaemonController::GetInstance()) - chromeos::IBusDaemonController::GetInstance()->AddObserver(this); + UpdateContextFocusState(); + OnInputMethodChanged(); } InputMethodIBus::~InputMethodIBus() { AbandonAllPendingKeyEvents(); - if (IsContextReady()) - DestroyContext(); - if (GetInputContextClient()) - GetInputContextClient()->SetInputContextHandler(NULL); - if (chromeos::IBusDaemonController::GetInstance()) - chromeos::IBusDaemonController::GetInstance()->RemoveObserver(this); + context_focused_ = false; + ConfirmCompositionText(); + // We are dead, so we need to ask the client to stop relying on us. + OnInputMethodChanged(); + + chromeos::IBusBridge::Get()->SetInputContextHandler(NULL); } void InputMethodIBus::OnFocus() { @@ -131,18 +117,6 @@ bool InputMethodIBus::OnUntranslatedIMEMessage(const base::NativeEvent& event, return false; } -void InputMethodIBus::Init(bool focused) { - // Initializes the connection to ibus daemon. It may happen asynchronously, - // and as soon as the connection is established, the |context_| will be - // created automatically. - - // Create the input context if the connection is already established. - if (IsConnected()) - CreateContext(); - - InputMethodBase::Init(focused); -} - void InputMethodIBus::ProcessKeyEventDone(uint32 id, XEvent* event, uint32 ibus_keyval, @@ -193,10 +167,8 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. // Note: We need to send the key event to ibus even if the |context_| is not // enabled, so that ibus can have a chance to enable the |context_|. - if (!context_focused_ || - GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || - !GetInputContextClient() || - GetInputContextClient()->IsXKBLayout()) { + if (!context_focused_ || !GetEngine() || + GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD ) { if (native_event->type == KeyPress) { if (ExecuteCharacterComposer(ibus_keyval, ibus_keycode, ibus_state)) { // Treating as PostIME event if character composer handles key event and @@ -214,24 +186,22 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { pending_key_events_.insert(current_keyevent_id_); // Since |native_event| might be treated as XEvent whose size is bigger than - // XKeyEvent e.g. in CopyNativeEvent() in ui/base/events/event.cc, allocating + // XKeyEvent e.g. in CopyNativeEvent() in ui/events/event.cc, allocating // |event| as XKeyEvent and casting it to XEvent is unsafe. crbug.com/151884 XEvent* event = new XEvent; *event = *native_event; - const chromeos::IBusInputContextClient::ProcessKeyEventCallback callback = + GetEngine()->ProcessKeyEvent( + ibus_keyval, + ibus_keycode, + ibus_state, base::Bind(&InputMethodIBus::ProcessKeyEventDone, weak_ptr_factory_.GetWeakPtr(), current_keyevent_id_, base::Owned(event), // Pass the ownership of |event|. ibus_keyval, ibus_keycode, - ibus_state); + ibus_state)); - GetInputContextClient()->ProcessKeyEvent(ibus_keyval, - ibus_keycode, - ibus_state, - callback, - base::Bind(callback, false)); ++current_keyevent_id_; // We don't want to suppress the result generated by this key event, but it @@ -255,9 +225,11 @@ bool InputMethodIBus::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) { } void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { - if (IsContextReady() && IsTextInputClientFocused(client)) { + if (IsTextInputClientFocused(client)) { ResetContext(); UpdateContextFocusState(); + if (previous_textinput_type_ != client->GetTextInputType()) + OnInputMethodChanged(); } InputMethodBase::OnTextInputTypeChanged(client); } @@ -276,18 +248,22 @@ void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { composition_head = rect; } - GetInputContextClient()->SetCursorLocation( + chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = + chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); + if (!candidate_window) + return; + candidate_window->SetCursorLocation( GfxRectToIBusRect(rect), GfxRectToIBusRect(composition_head)); - ui::Range text_range; - ui::Range selection_range; + gfx::Range text_range; + gfx::Range selection_range; string16 surrounding_text; if (!GetTextInputClient()->GetTextRange(&text_range) || !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text) || !GetTextInputClient()->GetSelectionRange(&selection_range)) { previous_surrounding_text_.clear(); - previous_selection_range_ = ui::Range::InvalidRange(); + previous_selection_range_ = gfx::Range::InvalidRange(); return; } @@ -308,7 +284,9 @@ void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { // Here SetSurroundingText accepts relative position of |surrounding_text|, so // we have to convert |selection_range| from node coordinates to // |surrounding_text| coordinates. - GetInputContextClient()->SetSurroundingText( + if (!GetEngine()) + return; + GetEngine()->SetSurroundingText( UTF16ToUTF8(surrounding_text), selection_range.start() - text_range.start(), selection_range.end() - text_range.start()); @@ -360,61 +338,6 @@ void InputMethodIBus::OnDidChangeFocusedClient(TextInputClient* focused_before, OnCaretBoundsChanged(focused); } -void InputMethodIBus::CreateContext() { - DCHECK(IsConnected()); - - if (input_context_state_ != INPUT_CONTEXT_STOP) { - DVLOG(1) << "Input context is already created or waiting ibus-daemon" - " response."; - return; - } - - input_context_state_ = INPUT_CONTEXT_WAIT_CREATE_INPUT_CONTEXT_RESPONSE; - - // Creates the input context asynchronously. - DCHECK(!IsContextReady()); - chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( - kClientName, - base::Bind(&InputMethodIBus::CreateInputContextDone, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&InputMethodIBus::CreateInputContextFail, - weak_ptr_factory_.GetWeakPtr())); -} - -void InputMethodIBus::SetUpSignalHandlers() { - DCHECK(IsContextReady()); - - // We should reset the handler to NULL before |this| is deleted so handler - // functions are not called after |this| is deleted. - GetInputContextClient()->SetInputContextHandler(this); - - GetInputContextClient()->SetCapabilities( - kIBusCapabilityPreeditText | kIBusCapabilityFocus | - kIBusCapabilitySurroundingText); - - UpdateContextFocusState(); - // Since ibus-daemon is launched in an on-demand basis on Chrome OS, RWHVA (or - // equivalents) might call OnCaretBoundsChanged() before the daemon starts. To - // save the case, call OnCaretBoundsChanged() here. - OnCaretBoundsChanged(GetTextInputClient()); - OnInputMethodChanged(); -} - -void InputMethodIBus::DestroyContext() { - if (input_context_state_ == INPUT_CONTEXT_STOP) - return; - input_context_state_ = INPUT_CONTEXT_STOP; - chromeos::IBusInputContextClient* input_context = GetInputContextClient(); - if (!input_context) - return; - if (input_context->IsObjectProxyReady()) { - // We can't use IsContextReady here because we want to destroy object proxy - // regardless of connection. The IsContextReady contains connection check. - ResetInputContext(); - DCHECK(!IsContextReady()); - } -} - void InputMethodIBus::ConfirmCompositionText() { TextInputClient* client = GetTextInputClient(); if (client && client->HasCompositionText()) @@ -453,17 +376,13 @@ void InputMethodIBus::ResetContext() { // Note: some input method engines may not support reset method, such as // ibus-anthy. But as we control all input method engines by ourselves, we can // make sure that all of the engines we are using support it correctly. - GetInputContextClient()->Reset(); + if (GetEngine()) + GetEngine()->Reset(); character_composer_.Reset(); } void InputMethodIBus::UpdateContextFocusState() { - if (!IsContextReady()) { - context_focused_ = false; - return; - } - const bool old_context_focused = context_focused_; // Use switch here in case we are going to add more text input types. switch (GetTextInputType()) { @@ -475,19 +394,16 @@ void InputMethodIBus::UpdateContextFocusState() { context_focused_ = true; break; } + if (!GetEngine()) + return; // We only focus in |context_| when the focus is in a normal textfield. // ibus_input_context_focus_{in|out}() run asynchronously. - if (old_context_focused && !context_focused_) - GetInputContextClient()->FocusOut(); - else if (!old_context_focused && context_focused_) - GetInputContextClient()->FocusIn(); - - if (context_focused_) { - uint32 capability = kIBusCapabilityFocus | kIBusCapabilitySurroundingText; - if (CanComposeInline()) - capability |= kIBusCapabilityPreeditText; - GetInputContextClient()->SetCapabilities(capability); + if (old_context_focused && !context_focused_) { + GetEngine()->FocusOut(); + } else if (!old_context_focused && context_focused_) { + GetEngine()->FocusIn(); + OnCaretBoundsChanged(GetTextInputClient()); } } @@ -723,6 +639,13 @@ void InputMethodIBus::UpdatePreeditText(const chromeos::IBusText& text, if (suppress_next_result_ || IsTextInputTypeNone()) return; + if (!CanComposeInline()) { + chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = + chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); + if (candidate_window) + candidate_window->UpdatePreeditText(text.text(), cursor_pos, visible); + } + // |visible| argument is very confusing. For example, what's the correct // behavior when: // 1. OnUpdatePreeditText() is called with a text and visible == false, then @@ -777,71 +700,6 @@ void InputMethodIBus::DeleteSurroundingText(int32 offset, uint32 length) { GetTextInputClient()->ExtendSelectionAndDelete(length, 0U); } -void InputMethodIBus::ResetInputContext() { - context_focused_ = false; - - ConfirmCompositionText(); - - // We are dead, so we need to ask the client to stop relying on us. - OnInputMethodChanged(); - GetInputContextClient()->ResetObjectProxy(); -} - -void InputMethodIBus::CreateInputContextDone( - const dbus::ObjectPath& object_path) { - DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); - - if (input_context_state_ == INPUT_CONTEXT_STOP) { - // DestroyContext has already been called. - return; - } - - chromeos::DBusThreadManager::Get()->GetIBusInputContextClient() - ->Initialize(chromeos::DBusThreadManager::Get()->GetIBusBus(), - object_path); - - input_context_state_ = INPUT_CONTEXT_RUNNING; - DCHECK(IsContextReady()); - SetUpSignalHandlers(); -} - -void InputMethodIBus::CreateInputContextFail() { - DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); - if (input_context_state_ == INPUT_CONTEXT_STOP) { - // CreateInputContext failed but the input context is no longer - // necessary, thus do nothing. - return; - } - - if (++create_input_context_fail_count_ >= kMaxRetryCount) { - DVLOG(1) << "CreateInputContext failed even tried " - << kMaxRetryCount << " times, give up."; - create_input_context_fail_count_ = 0; - input_context_state_ = INPUT_CONTEXT_STOP; - return; - } - - // Try CreateInputContext again. - chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( - kClientName, - base::Bind(&InputMethodIBus::CreateInputContextDone, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&InputMethodIBus::CreateInputContextFail, - weak_ptr_factory_.GetWeakPtr())); -} - -bool InputMethodIBus::IsConnected() { - return chromeos::DBusThreadManager::Get()->GetIBusBus() != NULL; -} - -bool InputMethodIBus::IsContextReady() { - if (!IsConnected()) - return false; - if (!GetInputContextClient()) - return false; - return GetInputContextClient()->IsObjectProxyReady(); -} - bool InputMethodIBus::ExecuteCharacterComposer(uint32 ibus_keyval, uint32 ibus_keycode, uint32 ibus_state) { @@ -866,20 +724,6 @@ bool InputMethodIBus::ExecuteCharacterComposer(uint32 ibus_keyval, return consumed; } -void InputMethodIBus::OnConnected() { - DCHECK(IsConnected()); - // If already input context is initialized, do nothing. - if (IsContextReady()) - return; - - DestroyContext(); - CreateContext(); -} - -void InputMethodIBus::OnDisconnected() { - DestroyContext(); -} - void InputMethodIBus::ExtractCompositionText( const chromeos::IBusText& text, uint32 cursor_position, @@ -907,7 +751,7 @@ void InputMethodIBus::ExtractCompositionText( size_t cursor_offset = char16_offsets[std::min(char_length, cursor_position)]; - out_composition->selection = Range(cursor_offset); + out_composition->selection = gfx::Range(cursor_offset); const std::vector<chromeos::IBusText::UnderlineAttribute>& underline_attributes = text.underline_attributes(); |