Index: ui/base/ime/input_method_ibus.cc |
diff --git a/ui/views/ime/input_method_ibus.cc b/ui/base/ime/input_method_ibus.cc |
similarity index 70% |
copy from ui/views/ime/input_method_ibus.cc |
copy to ui/base/ime/input_method_ibus.cc |
index 3f3a6b881a5024d696578207da1adbca3ae36e56..93b2cbe4226f64f997c821585fa0feb9c82200b5 100644 |
--- a/ui/views/ime/input_method_ibus.cc |
+++ b/ui/base/ime/input_method_ibus.cc |
@@ -2,13 +2,13 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "ui/views/ime/input_method_ibus.h" |
+#include "ui/base/ime/input_method_ibus.h" |
#include <ibus.h> |
-#if defined(TOUCH_UI) |
+ |
+#include <X11/X.h> |
#include <X11/Xlib.h> |
#include <X11/Xutil.h> |
-#endif |
#include <algorithm> |
#include <cstring> |
@@ -16,28 +16,24 @@ |
#include <vector> |
#include "base/basictypes.h" |
-#include "base/command_line.h" |
#include "base/i18n/char_iterator.h" |
#include "base/logging.h" |
#include "base/string_util.h" |
#include "base/third_party/icu/icu_utf.h" |
#include "base/utf_string_conversions.h" |
+#include "ui/base/events.h" |
+#include "ui/base/ime/text_input_client.h" |
#include "ui/base/keycodes/keyboard_codes.h" |
-#include "ui/gfx/point.h" |
-#include "ui/gfx/rect.h" |
-#include "ui/views/events/event.h" |
-#include "ui/views/widget/widget.h" |
- |
-#if defined(USE_AURA) |
+#include "ui/base/keycodes/keyboard_code_conversion.h" |
#include "ui/base/keycodes/keyboard_code_conversion_x.h" |
-#elif defined(TOOLKIT_USES_GTK) |
-#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" |
-#endif |
+#include "ui/gfx/rect.h" |
namespace { |
-// A global flag to switch the InputMethod implementation to InputMethodIBus |
-bool inputmethod_ibus_enabled = false; |
+XKeyEvent* GetKeyEvent(XEvent* event) { |
+ DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); |
+ return &event->xkey; |
+} |
// Converts ibus key state flags to event flags. |
int EventFlagsFromIBusState(guint32 state) { |
@@ -50,54 +46,37 @@ int EventFlagsFromIBusState(guint32 state) { |
(state & IBUS_BUTTON3_MASK ? ui::EF_RIGHT_BUTTON_DOWN : 0); |
} |
-// Converts event flags to ibus key state flags. |
-guint32 IBusStateFromEventFlags(int flags) { |
- return (flags & ui::EF_CAPS_LOCK_DOWN ? IBUS_LOCK_MASK : 0) | |
- (flags & ui::EF_CONTROL_DOWN ? IBUS_CONTROL_MASK : 0) | |
- (flags & ui::EF_SHIFT_DOWN ? IBUS_SHIFT_MASK : 0) | |
- (flags & ui::EF_ALT_DOWN ? IBUS_MOD1_MASK : 0) | |
- (flags & ui::EF_LEFT_BUTTON_DOWN ? IBUS_BUTTON1_MASK : 0) | |
- (flags & ui::EF_MIDDLE_BUTTON_DOWN ? IBUS_BUTTON2_MASK : 0) | |
- (flags & ui::EF_RIGHT_BUTTON_DOWN ? IBUS_BUTTON3_MASK : 0); |
-} |
- |
-void IBusKeyEventFromViewsKeyEvent(const views::KeyEvent& key, |
- guint32* ibus_keyval, |
- guint32* ibus_keycode, |
- guint32* ibus_state) { |
-#if defined(USE_AURA) |
- // TODO(yusukes): Handle native_event()? |
- *ibus_keyval = ui::XKeysymForWindowsKeyCode( |
- key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown()); |
- *ibus_keycode = 0; |
-#elif defined(TOUCH_UI) |
- if (key.native_event()) { |
- XKeyEvent* x_key = reinterpret_cast<XKeyEvent*>(key.native_event()); |
- // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't |
- // translate Shift and CapsLock states. |
- KeySym keysym = NoSymbol; |
- ::XLookupString(x_key, NULL, 0, &keysym, NULL); |
- *ibus_keyval = keysym; |
- *ibus_keycode = x_key->keycode; |
- } else { |
- *ibus_keyval = ui::XKeysymForWindowsKeyCode( |
- key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown()); |
- *ibus_keycode = 0; |
- } |
-#elif defined(TOOLKIT_USES_GTK) |
- if (key.gdk_event()) { |
- GdkEventKey* gdk_key = reinterpret_cast<GdkEventKey*>(key.gdk_event()); |
- *ibus_keyval = gdk_key->keyval; |
- *ibus_keycode = gdk_key->hardware_keycode; |
- } else { |
- *ibus_keyval = ui::GdkKeyCodeForWindowsKeyCode( |
- key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown()); |
- *ibus_keycode = 0; |
- } |
-#endif |
- |
- *ibus_state = IBusStateFromEventFlags(key.flags()); |
- if (key.type() == ui::ET_KEY_RELEASED) |
+// Converts X flags to ibus key state flags. |
+guint32 IBusStateFromXFlags(unsigned int flags) { |
+ return (flags & LockMask ? IBUS_LOCK_MASK : 0U) | |
+ (flags & ControlMask ? IBUS_CONTROL_MASK : 0U) | |
+ (flags & ShiftMask ? IBUS_SHIFT_MASK : 0U) | |
+ (flags & Mod1Mask ? IBUS_MOD1_MASK : 0U) | |
+ (flags & Button1Mask ? IBUS_BUTTON1_MASK : 0U) | |
+ (flags & Button2Mask ? IBUS_BUTTON2_MASK : 0U) | |
+ (flags & Button3Mask ? IBUS_BUTTON3_MASK : 0U); |
+} |
+ |
+// Converts X flags to event flags. |
+guint32 EventFlagsFromXFlags(unsigned int flags) { |
+ return EventFlagsFromIBusState(IBusStateFromXFlags(flags)); |
+} |
+ |
+void IBusKeyEventFromNativeKeyEvent(const base::NativeEvent& native_event, |
+ guint32* ibus_keyval, |
+ guint32* ibus_keycode, |
+ guint32* ibus_state) { |
+ DCHECK(native_event); // A fabricated event is not supported here. |
+ XKeyEvent* x_key = GetKeyEvent(native_event); |
+ |
+ // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't |
+ // translate Shift and CapsLock states. |
+ KeySym keysym = NoSymbol; |
+ ::XLookupString(x_key, NULL, 0, &keysym, NULL); |
+ *ibus_keyval = keysym; |
+ *ibus_keycode = x_key->keycode; |
+ *ibus_state = IBusStateFromXFlags(x_key->state); |
+ if (native_event->type == KeyRelease) |
*ibus_state |= IBUS_RELEASE_MASK; |
} |
@@ -174,22 +153,20 @@ void ExtractCompositionTextFromIBusPreedit(IBusText* text, |
} |
} |
-// A switch to enable InputMethodIBus |
-const char kEnableInputMethodIBusSwitch[] = "enable-inputmethod-ibus"; |
- |
} // namespace |
-namespace views { |
+namespace ui { |
-// InputMethodIBus::PendingKeyEvent implementation ---------------------------- |
+// InputMethodIBus::PendingKeyEvent implementation ------------------------ |
class InputMethodIBus::PendingKeyEvent { |
public: |
- PendingKeyEvent(InputMethodIBus* input_method, const KeyEvent& key, |
+ PendingKeyEvent(InputMethodIBus* input_method, |
+ const base::NativeEvent& native_event, |
guint32 ibus_keyval); |
~PendingKeyEvent(); |
// Abandon this pending key event. Its result will just be discarded. |
- void abandon() { input_method_ = NULL; } |
+ void Abandon() { input_method_ = NULL; } |
InputMethodIBus* input_method() const { return input_method_; } |
@@ -200,43 +177,31 @@ class InputMethodIBus::PendingKeyEvent { |
private: |
InputMethodIBus* input_method_; |
- // Complete information of a views::KeyEvent. Sadly, views::KeyEvent doesn't |
- // support copy. |
- ui::EventType type_; |
- int flags_; |
- ui::KeyboardCode key_code_; |
- uint16 character_; |
- uint16 unmodified_character_; |
- |
- guint32 ibus_keyval_; |
+ // TODO(yusukes): To support a fabricated key event (which is typically from |
+ // a virtual keyboard), we might have to copy event type, event flags, key |
+ // code, 'character_', and 'unmodified_character_'. See views::InputMethodIBus |
+ // for details. |
-#if defined(TOUCH_UI) |
- // corresponding XEvent data of a views::KeyEvent. It's a plain struct so we |
- // can do bitwise copy. |
+ // corresponding XEvent data of a key event. It's a plain struct so we can do |
+ // bitwise copy. |
XKeyEvent x_event_; |
-#endif |
+ |
+ const guint32 ibus_keyval_; |
DISALLOW_COPY_AND_ASSIGN(PendingKeyEvent); |
}; |
-InputMethodIBus::PendingKeyEvent::PendingKeyEvent(InputMethodIBus* input_method, |
- const KeyEvent& key, |
- guint32 ibus_keyval) |
+InputMethodIBus::PendingKeyEvent::PendingKeyEvent( |
+ InputMethodIBus* input_method, |
+ const base::NativeEvent& native_event, |
+ guint32 ibus_keyval) |
: input_method_(input_method), |
- type_(key.type()), |
- flags_(key.flags()), |
- key_code_(key.key_code()), |
- character_(key.GetCharacter()), |
- unmodified_character_(key.GetUnmodifiedCharacter()), |
ibus_keyval_(ibus_keyval) { |
DCHECK(input_method_); |
-#if defined(TOUCH_UI) |
- if (key.native_event()) |
- x_event_ = *reinterpret_cast<XKeyEvent*>(key.native_event()); |
- else |
- memset(&x_event_, 0, sizeof(x_event_)); |
-#endif |
+ // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). |
+ DCHECK(native_event); |
+ x_event_ = *GetKeyEvent(native_event); |
} |
InputMethodIBus::PendingKeyEvent::~PendingKeyEvent() { |
@@ -248,22 +213,19 @@ void InputMethodIBus::PendingKeyEvent::ProcessPostIME(bool handled) { |
if (!input_method_) |
return; |
-#if defined(TOUCH_UI) |
if (x_event_.type == KeyPress || x_event_.type == KeyRelease) { |
- KeyEvent key(reinterpret_cast<XEvent*>(&x_event_)); |
- input_method_->ProcessKeyEventPostIME(key, ibus_keyval_, handled); |
+ input_method_->ProcessKeyEventPostIME(reinterpret_cast<XEvent*>(&x_event_), |
+ ibus_keyval_, |
+ handled); |
return; |
} |
-#endif |
- KeyEvent key(type_, key_code_, flags_); |
- if (key_code_ == ui::VKEY_UNKNOWN) { |
- key.set_character(character_); |
- key.set_unmodified_character(unmodified_character_); |
- } |
- input_method_->ProcessKeyEventPostIME(key, ibus_keyval_, handled); |
+ |
+ // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). |
+ // See views::InputMethodIBus for details. Never forget to set 'character_' |
+ // and 'unmodified_character_' to support i18n VKs like a French VK! |
} |
-// InputMethodIBus::PendingCreateICRequest implementation --------------------- |
+// InputMethodIBus::PendingCreateICRequest implementation ----------------- |
class InputMethodIBus::PendingCreateICRequest { |
public: |
PendingCreateICRequest(InputMethodIBus* input_method, |
@@ -271,7 +233,7 @@ class InputMethodIBus::PendingCreateICRequest { |
~PendingCreateICRequest(); |
// Abandon this pending key event. Its result will just be discarded. |
- void abandon() { |
+ void Abandon() { |
input_method_ = NULL; |
request_ptr_ = NULL; |
} |
@@ -311,8 +273,9 @@ void InputMethodIBus::PendingCreateICRequest::StoreOrAbandonInputContext( |
} |
} |
-// InputMethodIBus implementation --------------------------------------------- |
-InputMethodIBus::InputMethodIBus(internal::InputMethodDelegate* delegate) |
+// InputMethodIBus implementation ----------------------------------------- |
+InputMethodIBus::InputMethodIBus( |
+ internal::InputMethodDelegate* delegate) |
: context_(NULL), |
pending_create_ic_request_(NULL), |
context_focused_(false), |
@@ -334,19 +297,17 @@ InputMethodIBus::~InputMethodIBus() { |
} |
void InputMethodIBus::OnFocus() { |
- DCHECK(!widget_focused()); |
InputMethodBase::OnFocus(); |
UpdateContextFocusState(); |
} |
void InputMethodIBus::OnBlur() { |
- DCHECK(widget_focused()); |
ConfirmCompositionText(); |
InputMethodBase::OnBlur(); |
UpdateContextFocusState(); |
} |
-void InputMethodIBus::Init(Widget* widget) { |
+void InputMethodIBus::Init(const base::NativeWindow& system_toplevel_window) { |
// Initializes the connection to ibus daemon. It may happen asynchronously, |
// and as soon as the connection is established, the |context_| will be |
// created automatically. |
@@ -363,33 +324,36 @@ void InputMethodIBus::Init(Widget* widget) { |
if (ibus_bus_is_connected(bus)) |
CreateContext(); |
- InputMethodBase::Init(widget); |
+ InputMethodBase::Init(system_toplevel_window); |
} |
-void InputMethodIBus::DispatchKeyEvent(const KeyEvent& key) { |
- DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); |
- DCHECK(widget_focused()); |
+void InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { |
+ DCHECK(native_event && (native_event->type == KeyPress || |
+ native_event->type == KeyRelease)); |
+ DCHECK(system_toplevel_window_focused()); |
guint32 ibus_keyval = 0; |
guint32 ibus_keycode = 0; |
guint32 ibus_state = 0; |
- IBusKeyEventFromViewsKeyEvent(key, &ibus_keyval, &ibus_keycode, &ibus_state); |
+ IBusKeyEventFromNativeKeyEvent( |
+ native_event, &ibus_keyval, &ibus_keycode, &ibus_state); |
// If |context_| is not usable, then we can only dispatch the key event as is. |
// We also dispatch the key event directly if the current text input type is |
- // ui::TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. |
+ // 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() == ui::TEXT_INPUT_TYPE_PASSWORD) { |
- if (key.type() == ui::ET_KEY_PRESSED) |
- ProcessUnfilteredKeyPressEvent(key, ibus_keyval); |
+ GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD) { |
+ if (native_event->type == KeyPress) |
+ ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); |
else |
- DispatchKeyEventPostIME(key); |
+ DispatchKeyEventPostIME(native_event); |
return; |
} |
- PendingKeyEvent* pending_key = new PendingKeyEvent(this, key, ibus_keyval); |
+ PendingKeyEvent* pending_key = |
+ new PendingKeyEvent(this, native_event, ibus_keyval); |
pending_key_events_.insert(pending_key); |
// Note: |
@@ -420,44 +384,35 @@ void InputMethodIBus::DispatchKeyEvent(const KeyEvent& key) { |
suppress_next_result_ = false; |
} |
-void InputMethodIBus::OnTextInputTypeChanged(View* view) { |
- if (context_ && IsViewFocused(view)) { |
+void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { |
+ if (context_ && IsTextInputClientFocused(client)) { |
ResetContext(); |
UpdateContextFocusState(); |
} |
- InputMethodBase::OnTextInputTypeChanged(view); |
+ InputMethodBase::OnTextInputTypeChanged(client); |
} |
-void InputMethodIBus::OnCaretBoundsChanged(View* view) { |
- if (!context_focused_ || !IsViewFocused(view)) |
+void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { |
+ if (!context_focused_ || !IsTextInputClientFocused(client)) |
return; |
// The current text input type should not be NONE if |context_| is focused. |
DCHECK(!IsTextInputTypeNone()); |
- |
- gfx::Rect rect = GetTextInputClient()->GetCaretBounds(); |
- gfx::Point origin = rect.origin(); |
- gfx::Point end = gfx::Point(rect.right(), rect.bottom()); |
- |
- // We need to convert the origin and end points separately, in case the View |
- // is scaled. |
- View::ConvertPointToScreen(view, &origin); |
- View::ConvertPointToScreen(view, &end); |
+ const gfx::Rect rect = GetTextInputClient()->GetCaretBounds(); |
// This function runs asynchronously. |
ibus_input_context_set_cursor_location( |
- context_, origin.x(), origin.y(), |
- end.x() - origin.x(), end.y() - origin.y()); |
+ context_, rect.x(), rect.y(), rect.width(), rect.height()); |
} |
-void InputMethodIBus::CancelComposition(View* view) { |
- if (context_focused_ && IsViewFocused(view)) |
+void InputMethodIBus::CancelComposition(const TextInputClient* client) { |
+ if (context_focused_ && IsTextInputClientFocused(client)) |
ResetContext(); |
} |
std::string InputMethodIBus::GetInputLocale() { |
// Not supported. |
- return std::string(""); |
+ return ""; |
} |
base::i18n::TextDirection InputMethodIBus::GetInputTextDirection() { |
@@ -469,35 +424,6 @@ bool InputMethodIBus::IsActive() { |
return true; |
} |
-// static |
-bool InputMethodIBus::IsInputMethodIBusEnabled() { |
-#if defined(TOUCH_UI) |
- return true; |
-#else |
- return inputmethod_ibus_enabled || |
- CommandLine::ForCurrentProcess()->HasSwitch( |
- kEnableInputMethodIBusSwitch); |
-#endif |
-} |
- |
-// static |
-void InputMethodIBus::SetEnableInputMethodIBus(bool enabled) { |
- inputmethod_ibus_enabled = enabled; |
-} |
- |
-void InputMethodIBus::OnWillChangeFocus(View* focused_before, View* focused) { |
- ConfirmCompositionText(); |
-} |
- |
-void InputMethodIBus::OnDidChangeFocus(View* focused_before, View* focused) { |
- UpdateContextFocusState(); |
- |
- // Force to update caret bounds, in case the View thinks that the caret |
- // bounds has not changed. |
- if (context_focused_) |
- OnCaretBoundsChanged(GetFocusedView()); |
-} |
- |
void InputMethodIBus::CreateContext() { |
DCHECK(!context_); |
DCHECK(GetIBus()); |
@@ -544,7 +470,7 @@ void InputMethodIBus::DestroyContext() { |
if (pending_create_ic_request_) { |
DCHECK(!context_); |
// |pending_create_ic_request_| will be deleted in CreateInputContextDone(). |
- pending_create_ic_request_->abandon(); |
+ pending_create_ic_request_->Abandon(); |
pending_create_ic_request_ = NULL; |
} else if (context_) { |
// ibus_proxy_destroy() will not really release the resource of |context_| |
@@ -556,7 +482,7 @@ void InputMethodIBus::DestroyContext() { |
} |
void InputMethodIBus::ConfirmCompositionText() { |
- ui::TextInputClient* client = GetTextInputClient(); |
+ TextInputClient* client = GetTextInputClient(); |
if (client && client->HasCompositionText()) |
client->ConfirmCompositionText(); |
@@ -567,8 +493,7 @@ void InputMethodIBus::ResetContext() { |
if (!context_focused_ || !GetTextInputClient()) |
return; |
- DCHECK(widget_focused()); |
- DCHECK(GetFocusedView()); |
+ DCHECK(system_toplevel_window_focused()); |
// Because ibus runs in asynchronous mode, the input method may still send us |
// results after sending out the reset request, so we use a flag to discard |
@@ -608,8 +533,8 @@ void InputMethodIBus::UpdateContextFocusState() { |
const bool old_context_focused = context_focused_; |
// Use switch here in case we are going to add more text input types. |
switch (GetTextInputType()) { |
- case ui::TEXT_INPUT_TYPE_NONE: |
- case ui::TEXT_INPUT_TYPE_PASSWORD: |
+ case TEXT_INPUT_TYPE_NONE: |
+ case TEXT_INPUT_TYPE_PASSWORD: |
context_focused_ = false; |
break; |
default: |
@@ -625,92 +550,134 @@ void InputMethodIBus::UpdateContextFocusState() { |
ibus_input_context_focus_in(context_); |
} |
-void InputMethodIBus::ProcessKeyEventPostIME(const KeyEvent& key, |
- guint32 ibus_keyval, |
- bool handled) { |
- // If we get here without a focused text input client, then it means the key |
- // event is sent to the global ibus input context. |
- if (!GetTextInputClient()) { |
- DispatchKeyEventPostIME(key); |
+void InputMethodIBus::ProcessKeyEventPostIME( |
+ const base::NativeEvent& native_event, |
+ guint32 ibus_keyval, |
+ bool handled) { |
+ TextInputClient* client = GetTextInputClient(); |
+ |
+ if (!client) { |
+ // As ibus works asynchronously, there is a chance that the focused client |
+ // loses focus before this method gets called. |
+ DispatchKeyEventPostIME(native_event); |
return; |
} |
- const View* old_focused_view = GetFocusedView(); |
- |
- // Same reason as above DCHECK. |
- DCHECK(old_focused_view); |
- |
- if (key.type() == ui::ET_KEY_PRESSED && handled) |
- ProcessFilteredKeyPressEvent(key); |
+ if (native_event->type == KeyPress && handled) |
+ ProcessFilteredKeyPressEvent(native_event); |
// In case the focus was changed by the key event. The |context_| should have |
- // been reset when the focused view changed. |
- if (old_focused_view != GetFocusedView()) |
+ // been reset when the focused window changed. |
+ if (client != GetTextInputClient()) |
return; |
if (HasInputMethodResult()) |
- ProcessInputMethodResult(key, handled); |
+ ProcessInputMethodResult(native_event, handled); |
// In case the focus was changed when sending input method results to the |
- // focused View. |
- if (old_focused_view != GetFocusedView()) |
+ // focused window. |
+ if (client != GetTextInputClient()) |
return; |
- if (key.type() == ui::ET_KEY_PRESSED && !handled) |
- ProcessUnfilteredKeyPressEvent(key, ibus_keyval); |
- else if (key.type() == ui::ET_KEY_RELEASED) |
- DispatchKeyEventPostIME(key); |
+ if (native_event->type == KeyPress && !handled) |
+ ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); |
+ else if (native_event->type == KeyRelease) |
+ DispatchKeyEventPostIME(native_event); |
} |
-void InputMethodIBus::ProcessFilteredKeyPressEvent(const KeyEvent& key) { |
- if (NeedInsertChar()) { |
- DispatchKeyEventPostIME(key); |
- } else { |
- KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, key.flags()); |
- DispatchKeyEventPostIME(key); |
- } |
-} |
- |
-void InputMethodIBus::ProcessUnfilteredKeyPressEvent(const KeyEvent& key, |
- guint32 ibus_keyval) { |
- const View* old_focused_view = GetFocusedView(); |
- DispatchKeyEventPostIME(key); |
- |
- // We shouldn't dispatch the character anymore if the key event caused focus |
- // change. |
- if (old_focused_view != GetFocusedView()) |
+void InputMethodIBus::ProcessFilteredKeyPressEvent( |
+ const base::NativeEvent& native_event) { |
+ if (NeedInsertChar()) |
+ DispatchKeyEventPostIME(native_event); |
+ else |
+ DispatchFabricatedKeyEventPostIME( |
+ ET_KEY_PRESSED, |
+ VKEY_PROCESSKEY, |
+ EventFlagsFromXFlags(GetKeyEvent(native_event)->state)); |
+} |
+ |
+void InputMethodIBus::ProcessUnfilteredKeyPressEvent( |
+ const base::NativeEvent& native_event, guint32 ibus_keyval) { |
+ // For a fabricated event, ProcessUnfilteredFabricatedKeyPressEvent should be |
+ // called instead. |
+ DCHECK(native_event); |
+ |
+ TextInputClient* client = GetTextInputClient(); |
+ DispatchKeyEventPostIME(native_event); |
+ |
+ // We shouldn't dispatch the character anymore if the key event dispatch |
+ // caused focus change. For example, in the following scenario, |
+ // 1. visit a web page which has a <textarea>. |
+ // 2. click Omnibox. |
+ // 3. enable Korean IME, press A, then press Tab to move the focus to the web |
+ // page. |
+ // We should return here not to send the Tab key event to RWHV. |
+ if (client != GetTextInputClient()) |
return; |
// Process compose and dead keys |
if (character_composer_.FilterKeyPress(ibus_keyval)) { |
string16 composed = character_composer_.composed_character(); |
if (!composed.empty()) { |
- ui::TextInputClient* client = GetTextInputClient(); |
+ client = GetTextInputClient(); |
if (client) |
client->InsertText(composed); |
} |
return; |
} |
+ |
// If a key event was not filtered by |context_| and |character_composer_|, |
// then it means the key event didn't generate any result text. So we need |
// to send corresponding character to the focused text input client. |
+ client = GetTextInputClient(); |
+ |
+ const uint32 state = |
+ EventFlagsFromXFlags(GetKeyEvent(native_event)->state); |
+ uint16 ch = ui::DefaultSymbolFromXEvent(native_event); |
+ if (!ch) |
+ ch = ui::GetCharacterFromKeyCode( |
+ ui::KeyboardCodeFromNative(native_event), state); |
James Su
2011/11/29 04:25:53
need {}
Yusuke Sato
2011/11/29 09:06:36
Done.
|
- ui::TextInputClient* client = GetTextInputClient(); |
- char16 ch = key.GetCharacter(); |
- if (ch && client) |
- client->InsertChar(ch, key.flags()); |
+ if (client && ch) |
+ client->InsertChar(ch, state); |
} |
-void InputMethodIBus::ProcessInputMethodResult(const KeyEvent& key, |
- bool handled) { |
- ui::TextInputClient* client = GetTextInputClient(); |
+void InputMethodIBus::ProcessUnfilteredFabricatedKeyPressEvent( |
+ EventType type, KeyboardCode key_code, int flags, guint32 ibus_keyval) { |
+ TextInputClient* client = GetTextInputClient(); |
+ DispatchFabricatedKeyEventPostIME(type, key_code, flags); |
+ |
+ if (client != GetTextInputClient()) |
+ return; |
+ |
+ if (character_composer_.FilterKeyPress(ibus_keyval)) { |
+ string16 composed = character_composer_.composed_character(); |
+ if (!composed.empty()) { |
+ client = GetTextInputClient(); |
+ if (client) |
+ client->InsertText(composed); |
+ } |
+ return; |
+ } |
+ |
+ client = GetTextInputClient(); |
+ const uint16 ch = ui::GetCharacterFromKeyCode(key_code, flags); |
+ if (client && ch) |
+ client->InsertChar(ch, flags); |
+} |
+ |
+void InputMethodIBus::ProcessInputMethodResult( |
+ const base::NativeEvent& native_event, bool handled) { |
+ TextInputClient* client = GetTextInputClient(); |
DCHECK(client); |
if (result_text_.length()) { |
if (handled && NeedInsertChar()) { |
+ const uint32 state = |
+ EventFlagsFromXFlags(GetKeyEvent(native_event)->state); |
for (string16::const_iterator i = result_text_.begin(); |
i != result_text_.end(); ++i) { |
- client->InsertChar(*i, key.flags()); |
+ client->InsertChar(*i, state); |
} |
} else { |
client->InsertText(result_text_); |
@@ -744,9 +711,9 @@ bool InputMethodIBus::HasInputMethodResult() const { |
} |
void InputMethodIBus::SendFakeProcessKeyEvent(bool pressed) const { |
- KeyEvent key(pressed ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, |
- ui::VKEY_PROCESSKEY, 0); |
- DispatchKeyEventPostIME(key); |
+ DispatchFabricatedKeyEventPostIME(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED, |
+ VKEY_PROCESSKEY, |
+ 0); |
} |
void InputMethodIBus::FinishPendingKeyEvent(PendingKeyEvent* pending_key) { |
@@ -760,18 +727,19 @@ void InputMethodIBus::AbandonAllPendingKeyEvents() { |
for (std::set<PendingKeyEvent*>::iterator i = pending_key_events_.begin(); |
i != pending_key_events_.end(); ++i) { |
// The object will be deleted in ProcessKeyEventDone(). |
- (*i)->abandon(); |
+ (*i)->Abandon(); |
} |
pending_key_events_.clear(); |
} |
-void InputMethodIBus::OnCommitText(IBusInputContext* context, IBusText* text) { |
+void InputMethodIBus::OnCommitText( |
+ IBusInputContext* context, IBusText* text) { |
DCHECK_EQ(context_, context); |
if (suppress_next_result_ || !text || !text->text) |
return; |
// We need to receive input method result even if the text input type is |
- // ui::TEXT_INPUT_TYPE_NONE, to make sure we can always send correct |
+ // TEXT_INPUT_TYPE_NONE, to make sure we can always send correct |
// character for each key event to the focused text input client. |
if (!GetTextInputClient()) |
return; |
@@ -798,29 +766,23 @@ void InputMethodIBus::OnForwardKeyEvent(IBusInputContext* context, |
guint state) { |
DCHECK_EQ(context_, context); |
- ui::KeyboardCode key_code = ui::VKEY_UNKNOWN; |
-#if defined(USE_AURA) |
- key_code = ui::KeyboardCodeFromXKeysym(keyval); |
-#elif defined(TOOLKIT_USES_GTK) |
- key_code = ui::WindowsKeyCodeForGdkKeyCode(keyval); |
-#endif |
- |
- if (!key_code) |
+ KeyboardCode ui_key_code = KeyboardCodeFromXKeysym(keyval); |
+ if (!ui_key_code) |
return; |
- KeyEvent key(state & IBUS_RELEASE_MASK ? |
- ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED, |
- key_code, EventFlagsFromIBusState(state)); |
+ const EventType event = |
+ (state & IBUS_RELEASE_MASK) ? ET_KEY_RELEASED : ET_KEY_PRESSED; |
+ const int flags = EventFlagsFromIBusState(state); |
// It is not clear when the input method will forward us a fake key event. |
// If there is a pending key event, then we may already received some input |
// method results, so we dispatch this fake key event directly rather than |
// calling ProcessKeyEventPostIME(), which will clear pending input method |
// results. |
- if (key.type() == ui::ET_KEY_PRESSED) |
- ProcessUnfilteredKeyPressEvent(key, keyval); |
+ if (event == ET_KEY_PRESSED) |
+ ProcessUnfilteredFabricatedKeyPressEvent(event, ui_key_code, flags, keyval); |
else |
- DispatchKeyEventPostIME(key); |
+ DispatchFabricatedKeyEventPostIME(event, ui_key_code, flags); |
} |
void InputMethodIBus::OnShowPreeditText(IBusInputContext* context) { |
@@ -880,7 +842,7 @@ void InputMethodIBus::OnHidePreeditText(IBusInputContext* context) { |
composition_.Clear(); |
if (pending_key_events_.empty()) { |
- ui::TextInputClient* client = GetTextInputClient(); |
+ TextInputClient* client = GetTextInputClient(); |
if (client && client->HasCompositionText()) |
client->ClearCompositionText(); |
composition_changed_ = false; |
@@ -958,4 +920,4 @@ void InputMethodIBus::CreateInputContextDone(IBusBus* bus, |
delete data; |
} |
-} // namespace views |
+} // namespace ui |