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
3// found in the LICENSE file.
4
5#ifndef UI_BASE_IME_INPUT_METHOD_IBUS_H_
6#define UI_BASE_IME_INPUT_METHOD_IBUS_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/weak_ptr.h"
15#include "chromeos/dbus/ibus/ibus_input_context_client.h"
16#include "chromeos/ime/ibus_daemon_controller.h"
17#include "ui/base/ime/character_composer.h"
18#include "ui/base/ime/composition_text.h"
19#include "ui/base/ime/input_method_base.h"
20
21namespace dbus {
22class ObjectPath;
23}
24namespace chromeos {
25namespace ibus {
26class IBusText;
27}  // namespace ibus
28}  // namespace chromeos
29
30namespace ui {
31
32// A ui::InputMethod implementation based on IBus.
33class UI_EXPORT InputMethodIBus
34    : public InputMethodBase,
35      public chromeos::IBusInputContextHandlerInterface,
36      public chromeos::IBusDaemonController::Observer {
37 public:
38  explicit InputMethodIBus(internal::InputMethodDelegate* delegate);
39  virtual ~InputMethodIBus();
40
41  // Overridden from InputMethod:
42  virtual void OnFocus() OVERRIDE;
43  virtual void OnBlur() OVERRIDE;
44  virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
45                                        NativeEventResult* result) OVERRIDE;
46  virtual void Init(bool focused) OVERRIDE;
47  virtual bool DispatchKeyEvent(
48      const base::NativeEvent& native_key_event) OVERRIDE;
49  virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE;
50  virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE;
51  virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE;
52  virtual void CancelComposition(const TextInputClient* client) OVERRIDE;
53  virtual void OnInputLocaleChanged() OVERRIDE;
54  virtual std::string GetInputLocale() OVERRIDE;
55  virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE;
56  virtual bool IsActive() OVERRIDE;
57  virtual bool IsCandidatePopupOpen() const OVERRIDE;
58
59 protected:
60  // chromeos::IBusDaemonController::Observer overrides.
61  virtual void OnConnected() OVERRIDE;
62  virtual void OnDisconnected() OVERRIDE;
63
64  // Converts |text| into CompositionText.
65  void ExtractCompositionText(const chromeos::IBusText& text,
66                              uint32 cursor_position,
67                              CompositionText* out_composition) const;
68
69  // Process a key returned from the input method.
70  virtual void ProcessKeyEventPostIME(const base::NativeEvent& native_key_event,
71                                      uint32 ibus_state,
72                                      bool handled);
73
74  // Converts |native_event| to ibus representation.
75  virtual void IBusKeyEventFromNativeKeyEvent(
76      const base::NativeEvent& native_event,
77      uint32* ibus_keyval,
78      uint32* ibus_keycode,
79      uint32* ibus_state);
80
81  // Resets context and abandon all pending results and key events.
82  void ResetContext();
83
84 private:
85  enum InputContextState {
86    // The input context is not working.
87    INPUT_CONTEXT_STOP,
88    // The input context is waiting for CreateInputContext reply from
89    // ibus-daemon.
90    INPUT_CONTEXT_WAIT_CREATE_INPUT_CONTEXT_RESPONSE,
91    // The input context is working and ready to communicate with ibus-daemon.
92    INPUT_CONTEXT_RUNNING,
93  };
94  class PendingKeyEvent;
95
96  // Overridden from InputMethodBase:
97  virtual void OnWillChangeFocusedClient(TextInputClient* focused_before,
98                                         TextInputClient* focused) OVERRIDE;
99  virtual void OnDidChangeFocusedClient(TextInputClient* focused_before,
100                                        TextInputClient* focused) OVERRIDE;
101
102  // Creates context asynchronously.
103  void CreateContext();
104
105  // Sets necessary signal handlers.
106  void SetUpSignalHandlers();
107
108  // Destroys context.
109  void DestroyContext();
110
111  // Asks the client to confirm current composition text.
112  void ConfirmCompositionText();
113
114  // Checks the availability of focused text input client and update focus
115  // state.
116  void UpdateContextFocusState();
117
118  // Processes a key event that was already filtered by the input method.
119  // A VKEY_PROCESSKEY may be dispatched to the focused View.
120  void ProcessFilteredKeyPressEvent(const base::NativeEvent& native_key_event);
121
122  // Processes a key event that was not filtered by the input method.
123  void ProcessUnfilteredKeyPressEvent(const base::NativeEvent& native_key_event,
124                                      uint32 ibus_state);
125  void ProcessUnfilteredFabricatedKeyPressEvent(EventType type,
126                                                KeyboardCode key_code,
127                                                int event_flags);
128
129  // Sends input method result caused by the given key event to the focused text
130  // input client.
131  void ProcessInputMethodResult(const base::NativeEvent& native_key_event,
132                                bool filtered);
133
134  // Checks if the pending input method result needs inserting into the focused
135  // text input client as a single character.
136  bool NeedInsertChar() const;
137
138  // Checks if there is pending input method result.
139  bool HasInputMethodResult() const;
140
141  // Abandons all pending key events. It usually happends when we lose keyboard
142  // focus, the text input type is changed or we are destroyed.
143  void AbandonAllPendingKeyEvents();
144
145  // Releases context focus and confirms the composition text. Then destroy
146  // object proxy.
147  void ResetInputContext();
148
149  // Returns true if the connection to ibus-daemon is established.
150  bool IsConnected();
151
152  // Returns true if the input context is ready to use.
153  bool IsContextReady();
154
155  // Passes keyevent and executes character composition if necessary. Returns
156  // true if character composer comsumes key event.
157  bool ExecuteCharacterComposer(uint32 ibus_keyval,
158                                uint32 ibus_keycode,
159                                uint32 ibus_state);
160
161  // chromeos::IBusInputContextHandlerInterface overrides:
162  virtual void CommitText(const chromeos::IBusText& text) OVERRIDE;
163  virtual void ForwardKeyEvent(uint32 keyval,
164                               uint32 keycode,
165                               uint32 state) OVERRIDE;
166  virtual void ShowPreeditText() OVERRIDE;
167  virtual void HidePreeditText() OVERRIDE;
168  virtual void UpdatePreeditText(const chromeos::IBusText& text,
169                                 uint32 cursor_pos,
170                                 bool visible) OVERRIDE;
171  virtual void DeleteSurroundingText(int32 offset, uint32 length) OVERRIDE;
172
173  void CreateInputContextDone(const dbus::ObjectPath& object_path);
174  void CreateInputContextFail();
175  void ProcessKeyEventDone(uint32 id, XEvent* xevent,
176                           uint32 ibus_keyval, uint32 ibus_keycode,
177                           uint32 ibus_state, bool is_handled);
178
179  // All pending key events. Note: we do not own these object, we just save
180  // pointers to these object so that we can abandon them when necessary.
181  // They will be deleted in ProcessKeyEventDone().
182  std::set<uint32> pending_key_events_;
183
184  // Represents input context's state.
185  InputContextState input_context_state_;
186
187  // The count of CreateInputContext message failure.
188  int create_input_context_fail_count_;
189
190  // Pending composition text generated by the current pending key event.
191  // It'll be sent to the focused text input client as soon as we receive the
192  // processing result of the pending key event.
193  CompositionText composition_;
194
195  // Pending result text generated by the current pending key event.
196  // It'll be sent to the focused text input client as soon as we receive the
197  // processing result of the pending key event.
198  string16 result_text_;
199
200  string16 previous_surrounding_text_;
201  ui::Range previous_selection_range_;
202
203  // Indicates if input context is focused or not.
204  bool context_focused_;
205
206  // Indicates if there is an ongoing composition text.
207  bool composing_text_;
208
209  // Indicates if the composition text is changed or deleted.
210  bool composition_changed_;
211
212  // If it's true then all input method result received before the next key
213  // event will be discarded.
214  bool suppress_next_result_;
215
216  // The latest id of key event.
217  uint32 current_keyevent_id_;
218
219  // An object to compose a character from a sequence of key presses
220  // including dead key etc.
221  CharacterComposer character_composer_;
222
223  // Used for making callbacks.
224  base::WeakPtrFactory<InputMethodIBus> weak_ptr_factory_;
225
226  DISALLOW_COPY_AND_ASSIGN(InputMethodIBus);
227};
228
229}  // namespace ui
230
231#endif  // UI_BASE_IME_INPUT_METHOD_IBUS_H_
232