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