Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / ui / base / ime / input_method_tsf.cc
1 // Copyright (c) 2013 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 #include "ui/base/ime/input_method_tsf.h"
6
7 #include "ui/base/ime/text_input_client.h"
8 #include "ui/base/ime/win/tsf_bridge.h"
9 #include "ui/base/ime/win/tsf_event_router.h"
10
11 namespace ui {
12
13 class InputMethodTSF::TSFEventObserver : public TSFEventRouterObserver {
14  public:
15   TSFEventObserver() : is_candidate_popup_open_(false) {}
16
17   // Returns true if we know for sure that a candidate window (or IME suggest,
18   // etc.) is open.
19   bool IsCandidatePopupOpen() const { return is_candidate_popup_open_; }
20
21   // Overridden from TSFEventRouterObserver:
22   virtual void OnCandidateWindowCountChanged(size_t window_count) OVERRIDE {
23     is_candidate_popup_open_ = (window_count != 0);
24   }
25
26  private:
27   // True if we know for sure that a candidate window is open.
28   bool is_candidate_popup_open_;
29
30   DISALLOW_COPY_AND_ASSIGN(TSFEventObserver);
31 };
32
33 InputMethodTSF::InputMethodTSF(internal::InputMethodDelegate* delegate,
34                                HWND toplevel_window_handle)
35     : InputMethodWin(delegate, toplevel_window_handle),
36       tsf_event_observer_(new TSFEventObserver()),
37       tsf_event_router_(new TSFEventRouter(tsf_event_observer_.get())) {
38   // In non-Aura environment, appropriate callbacks to OnFocus() and OnBlur()
39   // are not implemented yet. To work around this limitation, here we use
40   // "always focused" model.
41   // TODO(ime): Fix the caller of OnFocus() and OnBlur() so that appropriate
42   // focus event will be passed.
43   InputMethodWin::OnFocus();
44 }
45
46 InputMethodTSF::~InputMethodTSF() {}
47
48 void InputMethodTSF::OnFocus() {
49   // Do not call baseclass' OnFocus() and discard the event being in
50   // "always focused" model.  See the comment in the constructor.
51   // TODO(ime): Implement OnFocus once the callers are fixed.
52
53   tsf_event_router_->SetManager(
54       ui::TSFBridge::GetInstance()->GetThreadManager());
55 }
56
57 void InputMethodTSF::OnBlur() {
58   // Do not call baseclass' OnBlur() and discard the event being in
59   // "always focused" model.  See the comment in the constructor.
60   // TODO(ime): Implement OnFocus once the callers are fixed.
61
62   tsf_event_router_->SetManager(NULL);
63 }
64
65 bool InputMethodTSF::OnUntranslatedIMEMessage(
66     const base::NativeEvent& event, InputMethod::NativeEventResult* result) {
67   LRESULT original_result = 0;
68   BOOL handled = FALSE;
69   // Even when TSF is enabled, following IMM32/Win32 messages must be handled.
70   switch (event.message) {
71     case WM_IME_REQUEST:
72       // Some TSF-native TIPs (Text Input Processors) such as ATOK and Mozc
73       // still rely on WM_IME_REQUEST message to implement reverse conversion.
74       original_result = OnImeRequest(
75           event.message, event.wParam, event.lParam, &handled);
76       break;
77     case WM_CHAR:
78     case WM_SYSCHAR:
79       // ui::InputMethod interface is responsible for handling Win32 character
80       // messages. For instance, we will be here in the following cases.
81       // - TIP is not activated. (e.g, the current language profile is English)
82       // - TIP does not handle and WM_KEYDOWN and WM_KEYDOWN is translated into
83       //   WM_CHAR by TranslateMessage API. (e.g, TIP is turned off)
84       // - Another application sends WM_CHAR through SendMessage API.
85       original_result = OnChar(
86           event.hwnd, event.message, event.wParam, event.lParam, &handled);
87       break;
88     case WM_DEADCHAR:
89     case WM_SYSDEADCHAR:
90       // See the comment in WM_CHAR/WM_SYSCHAR.
91       original_result = OnDeadChar(
92           event.message, event.wParam, event.lParam, &handled);
93       break;
94   }
95   if (result)
96     *result = original_result;
97   return !!handled;
98 }
99
100 void InputMethodTSF::OnTextInputTypeChanged(const TextInputClient* client) {
101   if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
102     return;
103   ui::TSFBridge::GetInstance()->CancelComposition();
104   ui::TSFBridge::GetInstance()->OnTextInputTypeChanged(client);
105 }
106
107 void InputMethodTSF::OnCaretBoundsChanged(const TextInputClient* client) {
108   if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
109     return;
110   ui::TSFBridge::GetInstance()->OnTextLayoutChanged();
111 }
112
113 void InputMethodTSF::CancelComposition(const TextInputClient* client) {
114   if (IsTextInputClientFocused(client) && IsWindowFocused(client))
115     ui::TSFBridge::GetInstance()->CancelComposition();
116 }
117
118 void InputMethodTSF::DetachTextInputClient(TextInputClient* client) {
119   InputMethodWin::DetachTextInputClient(client);
120   ui::TSFBridge::GetInstance()->RemoveFocusedClient(client);
121 }
122
123 bool InputMethodTSF::IsCandidatePopupOpen() const {
124   return tsf_event_observer_->IsCandidatePopupOpen();
125 }
126
127 void InputMethodTSF::OnWillChangeFocusedClient(TextInputClient* focused_before,
128                                                TextInputClient* focused) {
129   if (IsWindowFocused(focused_before)) {
130     ConfirmCompositionText();
131     ui::TSFBridge::GetInstance()->RemoveFocusedClient(focused_before);
132   }
133 }
134
135 void InputMethodTSF::OnDidChangeFocusedClient(TextInputClient* focused_before,
136                                               TextInputClient* focused) {
137   if (IsWindowFocused(focused) && IsTextInputClientFocused(focused)) {
138     ui::TSFBridge::GetInstance()->SetFocusedClient(
139         GetAttachedWindowHandle(focused), focused);
140
141     // Force to update the input type since client's TextInputStateChanged()
142     // function might not be called if text input types before the client loses
143     // focus and after it acquires focus again are the same.
144     OnTextInputTypeChanged(focused);
145
146     // Force to update caret bounds, in case the client thinks that the caret
147     // bounds has not changed.
148     OnCaretBoundsChanged(focused);
149   }
150   InputMethodWin::OnDidChangeFocusedClient(focused_before, focused);
151 }
152
153 void InputMethodTSF::ConfirmCompositionText() {
154   if (!IsTextInputTypeNone())
155     ui::TSFBridge::GetInstance()->ConfirmComposition();
156 }
157
158 }  // namespace ui