Index: ui/aura/desktop_host_linux.cc |
diff --git a/ui/aura/desktop_host_linux.cc b/ui/aura/desktop_host_linux.cc |
index 2de31e68518240eb3f72ad280935cb2d5cedc885..d6acdf2f5f9c2c117141968f842f584a9e82d9ad 100644 |
--- a/ui/aura/desktop_host_linux.cc |
+++ b/ui/aura/desktop_host_linux.cc |
@@ -12,11 +12,13 @@ |
#include <algorithm> |
+#include "base/event_types.h" |
#include "base/message_loop.h" |
#include "base/message_pump_x.h" |
#include "ui/aura/cursor.h" |
#include "ui/aura/desktop.h" |
#include "ui/aura/event.h" |
+#include "ui/base/ime/input_method_delegate.h" |
#include "ui/base/keycodes/keyboard_codes.h" |
#include "ui/base/touch/touch_factory.h" |
#include "ui/base/x/x11_util.h" |
@@ -26,6 +28,12 @@ |
#include <X11/extensions/XInput2.h> |
#include <X11/Xlib.h> |
+#if defined(HAVE_IBUS) |
+#include "ui/base/ime/input_method_ibus.h" |
+#else |
+#include "ui/base/ime/mock_input_method.h" |
+#endif |
+ |
using std::max; |
using std::min; |
@@ -181,48 +189,8 @@ int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) { |
return num_coalesed; |
} |
-// We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only |
-// generated for certain keys; see |
-// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. |
-bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { |
- if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) || |
- (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) || |
- (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) { |
- return true; |
- } |
- |
- switch (keycode) { |
- case ui::VKEY_BACK: |
- case ui::VKEY_RETURN: |
- case ui::VKEY_ESCAPE: |
- case ui::VKEY_SPACE: |
- case ui::VKEY_TAB: |
- // In addition to the keys listed at MSDN, we include other |
- // graphic-character and numpad keys. |
- case ui::VKEY_MULTIPLY: |
- case ui::VKEY_ADD: |
- case ui::VKEY_SUBTRACT: |
- case ui::VKEY_DECIMAL: |
- case ui::VKEY_DIVIDE: |
- case ui::VKEY_OEM_1: |
- case ui::VKEY_OEM_2: |
- case ui::VKEY_OEM_3: |
- case ui::VKEY_OEM_4: |
- case ui::VKEY_OEM_5: |
- case ui::VKEY_OEM_6: |
- case ui::VKEY_OEM_7: |
- case ui::VKEY_OEM_102: |
- case ui::VKEY_OEM_PLUS: |
- case ui::VKEY_OEM_COMMA: |
- case ui::VKEY_OEM_MINUS: |
- case ui::VKEY_OEM_PERIOD: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-class DesktopHostLinux : public DesktopHost { |
+class DesktopHostLinux : public DesktopHost, |
+ public ui::internal::InputMethodDelegate { |
public: |
explicit DesktopHostLinux(const gfx::Rect& bounds); |
virtual ~DesktopHostLinux(); |
@@ -241,6 +209,12 @@ class DesktopHostLinux : public DesktopHost { |
virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
virtual gfx::Point QueryMouseLocation() OVERRIDE; |
virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; |
+ virtual ui::InputMethod* GetInputMethod() OVERRIDE; |
+ |
+ // ui::internal::InputMethodDelegate Override. |
+ virtual void DispatchKeyEventPostIME(const base::NativeEvent& event) OVERRIDE; |
+ virtual void DispatchFabricatedKeyEventPostIME( |
+ ui::EventType type, ui::KeyboardCode key_code, int flags) OVERRIDE; |
// Returns true if there's an X window manager present... in most cases. Some |
// window managers (notably, ion3) don't implement enough of ICCCM for us to |
@@ -253,6 +227,13 @@ class DesktopHostLinux : public DesktopHost { |
Display* xdisplay_; |
::Window xwindow_; |
+ // The input method for the desktop. |
+#if defined(HAVE_IBUS) |
+ ui::InputMethodIBus input_method_; |
+#else |
+ ui::MockInputMethod input_method_; |
+#endif |
+ |
// Current Aura cursor. |
gfx::NativeCursor current_cursor_; |
@@ -266,6 +247,7 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
: desktop_(NULL), |
xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
xwindow_(0), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(input_method_(this)), |
current_cursor_(aura::kCursorNull), |
size_(bounds.size()) { |
xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), |
@@ -273,7 +255,7 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
bounds.width(), bounds.height(), |
0, 0, 0); |
- long event_mask = ButtonPressMask | ButtonReleaseMask | |
+ long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
KeyPressMask | KeyReleaseMask | |
ExposureMask | VisibilityChangeMask | |
StructureNotifyMask | PropertyChangeMask | |
@@ -286,6 +268,8 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
if (base::MessagePumpForUI::HasXInput2()) |
ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
#endif |
+ |
+ input_method_.Init(xwindow_); |
} |
DesktopHostLinux::~DesktopHostLinux() { |
@@ -303,19 +287,10 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( |
desktop_->Draw(); |
handled = true; |
break; |
- case KeyPress: { |
- KeyEvent keydown_event(xev, false); |
- handled = desktop_->DispatchKeyEvent(&keydown_event); |
- if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) { |
- KeyEvent char_event(xev, true); |
- handled |= desktop_->DispatchKeyEvent(&char_event); |
- } |
- break; |
- } |
+ case KeyPress: |
case KeyRelease: { |
- KeyEvent keyup_event(xev, false); |
- handled = desktop_->DispatchKeyEvent(&keyup_event); |
- break; |
+ input_method_.DispatchKeyEvent(xev); |
+ handled = true; |
} |
case ButtonPress: |
case ButtonRelease: { |
@@ -386,6 +361,14 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( |
XFreeEventData(xev->xgeneric.display, &last_event.xcookie); |
break; |
} |
+ case FocusIn: { |
+ input_method_.OnFocus(); |
+ break; |
+ } |
+ case FocusOut: { |
+ input_method_.OnBlur(); |
+ break; |
+ } |
case MapNotify: { |
// If there's no window manager running, we need to assign the X input |
// focus to our host window. |
@@ -498,6 +481,23 @@ bool DesktopHostLinux::IsWindowManagerPresent() { |
return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
} |
+ui::InputMethod* DesktopHostLinux::GetInputMethod() { |
+ return &input_method_; |
+} |
+ |
+void DesktopHostLinux::DispatchKeyEventPostIME(const base::NativeEvent& event) { |
+ KeyEvent aura_event(event, false /* is_char */); |
+ desktop_->DispatchKeyEvent(&aura_event); |
+ // We don't send a Char event here since the input method takes care of it. |
+} |
+ |
+void DesktopHostLinux::DispatchFabricatedKeyEventPostIME( |
+ ui::EventType type, ui::KeyboardCode key_code, int flags) { |
+ // Dispatch a ui::VKEY_PROCESSKEY event etc. generated by |input_method_|. |
+ KeyEvent aura_event(type, key_code, flags); |
+ desktop_->DispatchKeyEvent(&aura_event); |
+} |
+ |
} // namespace |
// static |