OLD | NEW |
---|---|
(Empty) | |
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 #include "chromeos/dbus/ibus/ibus_input_context_client.h" | |
6 | |
7 #include <string> | |
8 #include "base/bind.h" | |
9 #include "base/callback.h" | |
10 #include "chromeos/dbus/ibus/ibus_constants.h" | |
11 #include "chromeos/dbus/ibus/ibus_text.h" | |
12 #include "dbus/bus.h" | |
13 #include "dbus/message.h" | |
14 #include "dbus/object_path.h" | |
15 #include "dbus/object_proxy.h" | |
16 | |
17 namespace chromeos { | |
18 | |
19 namespace { | |
20 const char kIBusInputContextInterface[] = "org.freedesktop.IBus.InputContext"; | |
21 | |
22 // Signal names. | |
23 const char kCommitTextSignal[] = "CommitText"; | |
24 const char kForwardKeyEventSignal[] = "ForwardKeyEvent"; | |
25 const char kHidePreeditTextSignal[] = "HidePreeditSignal"; | |
26 const char kShowPreeditTextSignal[] = "ShowPreeditText"; | |
27 const char kUpdatePreeditTextSignal[] = "UpdatePreeditText"; | |
28 | |
29 // Method names. | |
30 const char kFocusInMethod[] = "FocusIn"; | |
31 const char kFocusOutMethod[] = "FocusOut"; | |
32 const char kResetMethod[] = "Reset"; | |
33 const char kSetCapabilitiesMethod[] = "SetCapabilities"; | |
34 const char kSetCursorLocationMethod[] = "SetCursorLocation"; | |
35 const char kProcessKeyEventMethod[] = "ProcessKeyEvent"; | |
36 | |
37 // The IBusInputContextClient implementation. | |
38 class IBusInputContextClientImpl : public IBusInputContextClient { | |
39 public: | |
40 IBusInputContextClientImpl() | |
41 : proxy_(NULL), | |
42 weak_ptr_factory_(this) { | |
43 } | |
44 | |
45 virtual ~IBusInputContextClientImpl() {} | |
46 | |
47 public: | |
48 // IBusInputContextClient override. | |
49 virtual void Initialize(dbus::Bus* bus, | |
50 const dbus::ObjectPath& object_path) OVERRIDE { | |
51 if (proxy_ != NULL) { | |
52 LOG(ERROR) << "IBusInputContextClient is already initialized."; | |
53 return; | |
54 } | |
55 proxy_ = bus->GetObjectProxy(kIBusServiceName, object_path); | |
56 | |
57 ConnectSignals(); | |
58 } | |
59 | |
60 // IBusInputContextClient override. | |
61 virtual void ResetObjectProxy() OVERRIDE { | |
62 // Do not delete proxy here, proxy object is managed by dbus::Bus object. | |
63 proxy_ = NULL; | |
64 } | |
65 | |
66 // IBusInputContextClient override. | |
67 virtual bool IsConnected() const OVERRIDE { | |
68 return proxy_ != NULL; | |
69 } | |
70 | |
71 // IBusInputContextClient override. | |
72 virtual void SetCommitTextHandler( | |
73 const CommitTextHandler& commit_text_handler) OVERRIDE { | |
74 if (!commit_text_handler_.is_null()) | |
75 commit_text_handler_.Reset(); | |
satorux1
2012/05/11 22:45:14
You don't have to Reset.
I thought we wanted to a
Seigo Nonaka
2012/05/12 00:54:38
Done.
| |
76 commit_text_handler_ = commit_text_handler; | |
77 } | |
78 | |
79 // IBusInputContextClient override. | |
80 virtual void SetForwardKeyEventHandler( | |
81 const ForwardKeyEventHandler& forward_key_event_handler) OVERRIDE { | |
82 if (!forward_key_event_handler_.is_null()) | |
83 forward_key_event_handler_.Reset(); | |
84 forward_key_event_handler_ = forward_key_event_handler; | |
85 } | |
86 | |
87 // IBusInputContextClient override. | |
88 virtual void SetUpdatePreeditTextHandler( | |
89 const UpdatePreeditTextHandler& update_preedit_text_handler) OVERRIDE { | |
90 if (!update_preedit_text_handler_.is_null()) | |
91 update_preedit_text_handler_.Reset(); | |
92 update_preedit_text_handler_ = update_preedit_text_handler; | |
93 } | |
94 | |
95 // IBusInputContextClient override. | |
96 virtual void SetShowPreeditTextHandler( | |
97 const ShowPreeditTextHandler& show_preedit_text_handler) OVERRIDE { | |
98 if (!show_preedit_text_handler_.is_null()) | |
99 show_preedit_text_handler_.Reset(); | |
100 show_preedit_text_handler_ = show_preedit_text_handler; | |
101 } | |
102 | |
103 // IBusInputContextClient override. | |
104 virtual void SetHidePreeditTextHandler( | |
105 const HidePreeditTextHandler& hide_preedit_text_handler) OVERRIDE { | |
106 if (hide_preedit_text_handler_.is_null()) | |
107 hide_preedit_text_handler_.Reset(); | |
108 hide_preedit_text_handler_ = hide_preedit_text_handler; | |
109 } | |
110 | |
111 // IBusInputContextClient override. | |
112 virtual void UnsetCommitTextHandler() OVERRIDE { | |
113 commit_text_handler_.Reset(); | |
114 } | |
115 | |
116 // IBusInputContextClient override. | |
117 virtual void UnsetForwardKeyEventHandler() OVERRIDE { | |
118 forward_key_event_handler_.Reset(); | |
119 } | |
120 | |
121 // IBusInputContextClient override. | |
122 virtual void UnsetUpdatePreeditTextHandler() OVERRIDE { | |
123 update_preedit_text_handler_.Reset(); | |
124 } | |
125 | |
126 // IBusInputContextClient override. | |
127 virtual void UnsetShowPreeditTextHandler() OVERRIDE { | |
128 show_preedit_text_handler_.Reset(); | |
129 } | |
130 | |
131 // IBusInputContextClient override. | |
132 virtual void UnsetHidePreeditTextHandler() OVERRIDE { | |
133 hide_preedit_text_handler_.Reset(); | |
134 } | |
135 | |
136 // IBusInputContextClient override. | |
137 virtual void SetCapabilities(uint32 capabilities) OVERRIDE { | |
138 dbus::MethodCall method_call(kIBusInputContextInterface, | |
139 kSetCapabilitiesMethod); | |
140 dbus::MessageWriter writer(&method_call); | |
141 writer.AppendUint32(capabilities); | |
142 proxy_->CallMethod(&method_call, | |
143 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
144 base::Bind(&IBusInputContextClientImpl::DefaultCallback, | |
145 kSetCapabilitiesMethod)); | |
146 } | |
147 | |
148 // IBusInputContextClient override. | |
149 virtual void FocusIn() OVERRIDE { | |
150 dbus::MethodCall method_call(kIBusInputContextInterface, kFocusInMethod); | |
151 proxy_->CallMethod(&method_call, | |
152 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
153 base::Bind(&IBusInputContextClientImpl::DefaultCallback, | |
154 kFocusInMethod)); | |
155 } | |
156 | |
157 // IBusInputContextClient override. | |
158 virtual void FocusOut() OVERRIDE { | |
159 dbus::MethodCall method_call(kIBusInputContextInterface, kFocusOutMethod); | |
160 proxy_->CallMethod(&method_call, | |
161 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
162 base::Bind(&IBusInputContextClientImpl::DefaultCallback, | |
163 kFocusOutMethod)); | |
164 } | |
165 | |
166 // IBusInputContextClient override. | |
167 virtual void Reset() OVERRIDE { | |
168 dbus::MethodCall method_call(kIBusInputContextInterface, kResetMethod); | |
169 proxy_->CallMethod(&method_call, | |
170 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
171 base::Bind(&IBusInputContextClientImpl::DefaultCallback, | |
172 kResetMethod)); | |
173 } | |
174 | |
175 // IBusInputContextClient override. | |
176 virtual void SetCursorLocation(int32 x, int32 y, int32 w, int32 h) OVERRIDE { | |
177 dbus::MethodCall method_call(kIBusInputContextInterface, | |
178 kSetCursorLocationMethod); | |
179 dbus::MessageWriter writer(&method_call); | |
180 writer.AppendInt32(x); | |
181 writer.AppendInt32(y); | |
182 writer.AppendInt32(w); | |
183 writer.AppendInt32(h); | |
184 proxy_->CallMethod(&method_call, | |
185 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
186 base::Bind(&IBusInputContextClientImpl::DefaultCallback, | |
187 kSetCursorLocationMethod)); | |
188 } | |
189 | |
190 // IBusInputContextClient override. | |
191 virtual void ProcessKeyEvent( | |
192 uint32 keyval, | |
193 uint32 keycode, | |
194 uint32 state, | |
195 const ProcessKeyEventCallback& callback) OVERRIDE { | |
196 dbus::MethodCall method_call(kIBusInputContextInterface, | |
197 kProcessKeyEventMethod); | |
198 dbus::MessageWriter writer(&method_call); | |
199 writer.AppendUint32(keyval); | |
200 writer.AppendUint32(keycode); | |
201 writer.AppendUint32(state); | |
202 proxy_->CallMethod( | |
203 &method_call, | |
204 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
205 base::Bind(&IBusInputContextClientImpl::OnProcessKeyEvent, | |
206 callback)); | |
207 } | |
208 | |
209 private: | |
210 // Handles no response method call reply. | |
211 static void DefaultCallback(const std::string& method_name, | |
212 dbus::Response* response) { | |
213 if (!response) { | |
214 LOG(ERROR) << "Failed to call method: " << method_name; | |
215 return; | |
216 } | |
217 } | |
218 | |
219 // Handles ProcessKeyEvent method call reply. | |
220 static void OnProcessKeyEvent(const ProcessKeyEventCallback& callback, | |
221 dbus::Response* response) { | |
222 if (!response) { | |
223 LOG(ERROR) << "Cannot get input context: " << response->ToString(); | |
224 return; | |
225 } | |
226 dbus::MessageReader reader(response); | |
227 bool is_keyevent_used; | |
228 if (!reader.PopBool(&is_keyevent_used)) { | |
229 // The IBus message structure may be changed. | |
230 LOG(ERROR) << "Invalid response: " << response->ToString(); | |
231 return; | |
232 } | |
233 DCHECK(!callback.is_null()); | |
234 callback.Run(is_keyevent_used); | |
235 } | |
236 | |
237 // Handles CommitText signal. | |
238 void OnCommitText(dbus::Signal* signal) { | |
239 if (commit_text_handler_.is_null()) | |
240 return; | |
241 dbus::MessageReader reader(signal); | |
242 IBusText ibus_text; | |
243 if (!PopIBusText(&reader, &ibus_text)) { | |
244 // The IBus message structure may be changed. | |
245 LOG(ERROR) << "Invalid signal: " << signal->ToString(); | |
246 return; | |
247 } | |
248 commit_text_handler_.Run(ibus_text); | |
249 } | |
250 | |
251 // Handles ForwardKeyEvetn signal. | |
252 void OnForwardKeyEvent(dbus::Signal* signal) { | |
253 if (forward_key_event_handler_.is_null()) | |
254 return; | |
255 dbus::MessageReader reader(signal); | |
256 uint32 keyval = 0; | |
257 uint32 keycode = 0; | |
258 uint32 state = 0; | |
259 if (!reader.PopUint32(&keyval) || | |
260 !reader.PopUint32(&keycode) || | |
261 !reader.PopUint32(&state)) { | |
262 // The IBus message structure may be changed. | |
263 LOG(ERROR) << "Invalid signal: " << signal->ToString(); | |
264 return; | |
265 } | |
266 forward_key_event_handler_.Run(keyval, keycode, state); | |
267 } | |
268 | |
269 // Handles UpdatePreeditText signal. | |
270 void OnUpdatePreeditText(dbus::Signal* signal) { | |
271 if (update_preedit_text_handler_.is_null()) | |
272 return; | |
273 dbus::MessageReader reader(signal); | |
274 IBusText ibus_text; | |
275 uint32 cursor_pos = 0; | |
276 bool visible = true; | |
277 if (!PopIBusText(&reader, &ibus_text) || | |
278 !reader.PopUint32(&cursor_pos) || | |
279 !reader.PopBool(&visible)) { | |
280 // The IBus message structure may be changed. | |
281 LOG(ERROR) << "Invalid signal: " << signal->ToString(); | |
282 return; | |
283 } | |
284 update_preedit_text_handler_.Run(ibus_text, cursor_pos, visible); | |
285 } | |
286 | |
287 // Handles ShowPreeditText signal. | |
288 void OnShowPreeditText(dbus::Signal* signal) { | |
289 if (!show_preedit_text_handler_.is_null()) | |
290 show_preedit_text_handler_.Run(); | |
291 } | |
292 | |
293 // Handles HidePreeditText signal. | |
294 void OnHidePreeditText(dbus::Signal* signal) { | |
295 if (!hide_preedit_text_handler_.is_null()) | |
296 hide_preedit_text_handler_.Run(); | |
297 } | |
298 | |
299 // Connects signals to signal handlers. | |
300 void ConnectSignals() { | |
301 proxy_->ConnectToSignal( | |
302 kIBusInputContextInterface, | |
303 kCommitTextSignal, | |
304 base::Bind(&IBusInputContextClientImpl::OnCommitText, | |
305 weak_ptr_factory_.GetWeakPtr()), | |
306 base::Bind(&IBusInputContextClientImpl::OnSignalConnected, | |
307 weak_ptr_factory_.GetWeakPtr())); | |
308 | |
309 proxy_->ConnectToSignal( | |
310 kIBusInputContextInterface, | |
311 kForwardKeyEventSignal, | |
312 base::Bind(&IBusInputContextClientImpl::OnForwardKeyEvent, | |
313 weak_ptr_factory_.GetWeakPtr()), | |
314 base::Bind(&IBusInputContextClientImpl::OnSignalConnected, | |
315 weak_ptr_factory_.GetWeakPtr())); | |
316 | |
317 proxy_->ConnectToSignal( | |
318 kIBusInputContextInterface, | |
319 kUpdatePreeditTextSignal, | |
320 base::Bind(&IBusInputContextClientImpl::OnUpdatePreeditText, | |
321 weak_ptr_factory_.GetWeakPtr()), | |
322 base::Bind(&IBusInputContextClientImpl::OnSignalConnected, | |
323 weak_ptr_factory_.GetWeakPtr())); | |
324 | |
325 proxy_->ConnectToSignal( | |
326 kIBusInputContextInterface, | |
327 kShowPreeditTextSignal, | |
328 base::Bind(&IBusInputContextClientImpl::OnShowPreeditText, | |
329 weak_ptr_factory_.GetWeakPtr()), | |
330 base::Bind(&IBusInputContextClientImpl::OnSignalConnected, | |
331 weak_ptr_factory_.GetWeakPtr())); | |
332 | |
333 proxy_->ConnectToSignal( | |
334 kIBusInputContextInterface, | |
335 kHidePreeditTextSignal, | |
336 base::Bind(&IBusInputContextClientImpl::OnHidePreeditText, | |
337 weak_ptr_factory_.GetWeakPtr()), | |
338 base::Bind(&IBusInputContextClientImpl::OnSignalConnected, | |
339 weak_ptr_factory_.GetWeakPtr())); | |
340 } | |
341 | |
342 // Handles the result of signal connection setup. | |
343 void OnSignalConnected(const std::string& interface, | |
344 const std::string& signal, | |
345 bool succeeded) { | |
346 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " | |
347 << signal << " failed."; | |
348 } | |
349 | |
350 dbus::ObjectProxy* proxy_; | |
351 | |
352 // Signal handlers. | |
353 CommitTextHandler commit_text_handler_; | |
354 ForwardKeyEventHandler forward_key_event_handler_; | |
355 HidePreeditTextHandler hide_preedit_text_handler_; | |
356 ShowPreeditTextHandler show_preedit_text_handler_; | |
357 UpdatePreeditTextHandler update_preedit_text_handler_; | |
358 | |
359 base::WeakPtrFactory<IBusInputContextClientImpl> weak_ptr_factory_; | |
360 | |
361 DISALLOW_COPY_AND_ASSIGN(IBusInputContextClientImpl); | |
362 }; | |
363 | |
364 // A stub implementation of IBusInputContextClient. | |
365 class IBusInputContextClientStubImpl : public IBusInputContextClient { | |
366 public: | |
367 IBusInputContextClientStubImpl() {} | |
368 | |
369 virtual ~IBusInputContextClientStubImpl() {} | |
370 | |
371 public: | |
372 // IBusInputContextClient override. | |
373 virtual void Initialize(dbus::Bus* bus, | |
374 const dbus::ObjectPath& object_path) OVERRIDE {} | |
375 // IBusInputContextClient override. | |
376 virtual void ResetObjectProxy() OVERRIDE {} | |
377 // IBusInputContextClient override. | |
378 virtual bool IsConnected() const OVERRIDE { | |
379 return true; | |
380 } | |
381 // IBusInputContextClient overrides. | |
382 virtual void SetCommitTextHandler( | |
383 const CommitTextHandler& commit_text_handler) OVERRIDE {} | |
384 virtual void SetForwardKeyEventHandler( | |
385 const ForwardKeyEventHandler& forward_key_event_handler) OVERRIDE {} | |
386 virtual void SetUpdatePreeditTextHandler( | |
387 const UpdatePreeditTextHandler& update_preedit_text_handler) OVERRIDE {} | |
388 virtual void SetShowPreeditTextHandler( | |
389 const ShowPreeditTextHandler& show_preedit_text_handler) OVERRIDE {} | |
390 virtual void SetHidePreeditTextHandler( | |
391 const HidePreeditTextHandler& hide_preedit_text_handler) OVERRIDE {} | |
392 virtual void UnsetCommitTextHandler() OVERRIDE {} | |
393 virtual void UnsetForwardKeyEventHandler() OVERRIDE {} | |
394 virtual void UnsetUpdatePreeditTextHandler() OVERRIDE {} | |
395 virtual void UnsetShowPreeditTextHandler() OVERRIDE {} | |
396 virtual void UnsetHidePreeditTextHandler() OVERRIDE {} | |
397 virtual void SetCapabilities(uint32 capability) OVERRIDE {} | |
398 virtual void FocusIn() OVERRIDE {} | |
399 virtual void FocusOut() OVERRIDE {} | |
400 virtual void Reset() OVERRIDE {} | |
401 virtual void SetCursorLocation(int32 x, int32 y, int32 w, int32 h) OVERRIDE {} | |
402 virtual void ProcessKeyEvent( | |
403 uint32 keyval, | |
404 uint32 keycode, | |
405 uint32 state, | |
406 const ProcessKeyEventCallback& callback) OVERRIDE {} | |
407 | |
408 private: | |
409 DISALLOW_COPY_AND_ASSIGN(IBusInputContextClientStubImpl); | |
410 }; | |
411 | |
412 } // namespace | |
413 | |
414 /////////////////////////////////////////////////////////////////////////////// | |
415 // IBusInputContextClient | |
416 | |
417 IBusInputContextClient::IBusInputContextClient() {} | |
418 | |
419 IBusInputContextClient::~IBusInputContextClient() {} | |
420 | |
421 // static | |
422 IBusInputContextClient* IBusInputContextClient::Create( | |
423 DBusClientImplementationType type) { | |
424 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) { | |
425 return new IBusInputContextClientImpl(); | |
426 } | |
427 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); | |
428 return new IBusInputContextClientStubImpl(); | |
429 } | |
430 } // namespace chromeos | |
OLD | NEW |