Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(943)

Unified Diff: ui/base/ime/remote_input_method_win.cc

Issue 67503004: Introduce RemoteInputMethodWin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/base/ime/remote_input_method_win.cc
diff --git a/ui/base/ime/remote_input_method_win.cc b/ui/base/ime/remote_input_method_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..456e589f575c5c9a8d921d9ff78fa91e62ed59d7
--- /dev/null
+++ b/ui/base/ime/remote_input_method_win.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/remote_input_method_win.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_delegate.h"
+#include "ui/base/ime/remote_input_method_delegate_win.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/base/ime/win/tsf_input_scope.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/rect.h"
+
+namespace ui {
+namespace {
+
+const LANGID kFallbackLangID =
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT);
+
+// Caveats: Currently we support only one instance at the same time.
Seigo Nonaka 2013/11/18 20:00:27 Could you describe why should we support multiple
yukawa 2013/11/19 07:17:51 I don't think we need to support multiple instance
+class InstanceMapper {
Seigo Nonaka 2013/11/18 20:00:27 Does this class is necessary? Seems there is only
yukawa 2013/11/19 07:17:51 Done.
+ public:
+ static void RegisterInstance(InputMethod* public_interface,
+ RemoteInputMethodPrivateWin* private_interface) {
+ CHECK(public_interface_ == NULL)
+ << "Currently only one instance is supported at the same time";
+ CHECK(private_interface_ == NULL)
+ << "Currently only one instance is supported at the same time";
+ public_interface_ = public_interface;
+ private_interface_ = private_interface;
+ }
+
+ static void UnregisterInstance(InputMethod* public_interface) {
+ RemoteInputMethodPrivateWin* private_interface =
+ GetPrivate(public_interface);
+ if (public_interface_ == public_interface &&
+ private_interface_ == private_interface) {
+ public_interface_ = NULL;
+ private_interface_ = NULL;
+ }
+ }
+
+ static RemoteInputMethodPrivateWin* GetPrivate(
+ InputMethod* public_interface) {
+ if (public_interface_ != public_interface)
+ return NULL;
+ return private_interface_;
+ }
+
+ private:
+ static InputMethod* public_interface_;
+ static RemoteInputMethodPrivateWin* private_interface_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceMapper);
+};
+InputMethod* InstanceMapper::public_interface_ = NULL;
+RemoteInputMethodPrivateWin* InstanceMapper::private_interface_ = NULL;
+
+std::string GetLocaleString(LCID Locale_id, LCTYPE locale_type) {
+ wchar_t buffer[16] = {};
+
+ //|chars_written| includes NUL terminator.
+ int chars_written =
+ GetLocaleInfo(Locale_id, locale_type, buffer, arraysize(buffer));
+ if (chars_written <= 1 || arraysize(buffer) < chars_written)
+ return std::string();
+ std::string result;
+ WideToUTF8(buffer, chars_written - 1, &result);
+ return result;
+}
+
+std::vector<int32> GetInputScopesAsInt(TextInputType text_input_type,
+ TextInputMode text_input_mode) {
+ std::vector<int32> result;
+ // An empty vector represents |text_input_type| is TEXT_INPUT_TYPE_NONE.
+ if (text_input_type == TEXT_INPUT_TYPE_NONE)
+ return result;
+
+ const std::vector<InputScope>& input_scopes =
+ tsf_inputscope::GetInputScopes(text_input_type, text_input_mode);
+ result.reserve(input_scopes.size());
+ for (size_t i = 0; i < input_scopes.size(); ++i)
+ result.push_back(static_cast<int32>(input_scopes[i]));
+ return result;
+}
+
+std::vector<gfx::Rect> GetCompositionCharacterBounds(
+ const TextInputClient* client) {
+ if (!client)
+ return std::vector<gfx::Rect>();
+
+ if (!client->HasCompositionText()) {
+ std::vector<gfx::Rect> caret;
+ caret.push_back(client->GetCaretBounds());
+ return caret;
+ }
+
+ std::vector<gfx::Rect> bounds;
+ for (uint32 i = 0;; ++i) {
+ gfx::Rect rect;
+ if (!client->GetCompositionCharacterBounds(i, &rect))
+ break;
+ bounds.push_back(rect);
+ }
+ return bounds;
+}
+
+class RemoteInputMethodWin : public InputMethod,
+ public RemoteInputMethodPrivateWin {
+ public:
+ explicit RemoteInputMethodWin(internal::InputMethodDelegate* delegate)
+ : delegate_(delegate),
+ remote_delegate_(NULL),
+ text_input_client_(NULL),
+ is_candidate_popup_open_(false),
+ is_ime_(false),
+ langid_(kFallbackLangID) {
+ InstanceMapper::RegisterInstance(this, this);
+ }
Seigo Nonaka 2013/11/18 20:00:27 plz add one line break between functions.
yukawa 2013/11/19 07:17:51 Done.
+ virtual ~RemoteInputMethodWin() {
+ InstanceMapper::UnregisterInstance(this);
+ }
+
+ private:
+ // Overridden from InputMethod:
+ virtual void SetDelegate(internal::InputMethodDelegate* delegate) OVERRIDE {
+ delegate_ = delegate;
+ }
+ virtual void Init(bool focused) OVERRIDE {}
+ virtual void OnFocus() OVERRIDE {}
+ virtual void OnBlur() OVERRIDE {}
+ virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+ NativeEventResult* result) OVERRIDE {
+ return false;
+ }
+ virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE {
+
+ std::vector<int32> prev_input_scopes;
+ std::swap(input_scopes_, prev_input_scopes);
+ std::vector<gfx::Rect> prev_bounds;
+ std::swap(composition_character_bounds_, prev_bounds);
+ if (client) {
+ input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
+ client->GetTextInputMode());
+ composition_character_bounds_ = GetCompositionCharacterBounds(client);
+ }
+
+ text_input_client_ = client;
+
+ if (!remote_delegate_ || (prev_input_scopes == input_scopes_ &&
+ prev_bounds == composition_character_bounds_))
+ return;
+ remote_delegate_->OnTextInputClientUpdated(
+ input_scopes_, composition_character_bounds_);
+ }
+ virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE {
+ if (text_input_client_ == client) {
Seigo Nonaka 2013/11/18 20:00:27 nit: I prefer early exit style but up to you.
yukawa 2013/11/19 07:17:51 Done. And simplified.
+ if (!input_scopes_.empty() || !composition_character_bounds_.empty()) {
+ input_scopes_.empty();
+ composition_character_bounds_.empty();
+ if (remote_delegate_) {
+ remote_delegate_->OnTextInputClientUpdated(
+ input_scopes_, composition_character_bounds_);
+ }
+ }
+ text_input_client_ = NULL;
+ }
+ }
+ virtual TextInputClient* GetTextInputClient() const OVERRIDE {
+ return text_input_client_;
+ }
+ virtual bool DispatchKeyEvent(const ui::KeyEvent& event) OVERRIDE {
+ if (event.HasNativeEvent())
Seigo Nonaka 2013/11/18 20:00:27 DCHECK?
yukawa 2013/11/19 07:17:51 Um, I changed my mind and added WM_CHAR handler be
Seigo Nonaka 2013/11/20 04:14:29 Let me confirm again, will RemoteInputMethodWin di
yukawa 2013/11/20 05:06:07 Do you mean we should do as follows? if (event.Ha
Seigo Nonaka 2013/11/20 05:40:41 Okay, as we talked offline, it seems good to imple
+ return false;
+
+ if (event.is_char() && text_input_client_) {
+ GetTextInputClient()->InsertChar(event.key_code(),
+ ui::GetModifiersFromKeyState());
+ return true;
+ }
+ if (!delegate_)
+ return false;
+ return delegate_->DispatchFabricatedKeyEventPostIME(event.type(),
+ event.key_code(),
+ event.flags());
+ }
+ virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE {
+ if (!text_input_client_ || text_input_client_ != client)
+ return;
+ std::vector<int32> prev_input_scopes;
+ std::swap(input_scopes_, prev_input_scopes);
+ input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
+ client->GetTextInputMode());
+ if (input_scopes_ != prev_input_scopes && remote_delegate_) {
+ remote_delegate_->OnTextInputClientUpdated(
+ input_scopes_, composition_character_bounds_);
+ }
+ }
+ virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE {
+ if (!text_input_client_ || text_input_client_ != client)
+ return;
+ std::vector<gfx::Rect> prev_rects;
+ std::swap(composition_character_bounds_, prev_rects);
+ composition_character_bounds_ = GetCompositionCharacterBounds(client);
+ if (composition_character_bounds_ != prev_rects && remote_delegate_) {
+ remote_delegate_->OnTextInputClientUpdated(
+ input_scopes_, composition_character_bounds_);
+ }
+ }
+ virtual void CancelComposition(const TextInputClient* client) OVERRIDE {
+ if (CanSendRemoteNotification(client))
+ remote_delegate_->CancelComposition();
+ }
+ virtual void OnInputLocaleChanged() OVERRIDE {
+ // not supported.
+ }
+ virtual std::string GetInputLocale() OVERRIDE {
+ const LCID locale_id = MAKELCID(langid_, SORT_DEFAULT);
+ std::string language =
+ GetLocaleString(locale_id, LOCALE_SISO639LANGNAME);
+ if (SUBLANGID(langid_) == SUBLANG_NEUTRAL || language.empty())
+ return language;
+ const std::string& region =
+ GetLocaleString(locale_id, LOCALE_SISO3166CTRYNAME);
+ if (region.empty())
+ return language;
+ return language.append(1, '-').append(region);
+ }
+ virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE {
+ switch (PRIMARYLANGID(langid_)) {
+ case LANG_ARABIC:
+ case LANG_HEBREW:
+ case LANG_PERSIAN:
+ case LANG_SYRIAC:
+ case LANG_UIGHUR:
+ case LANG_URDU:
+ return base::i18n::RIGHT_TO_LEFT;
+ default:
+ return base::i18n::LEFT_TO_RIGHT;
+ }
+ }
+ virtual bool IsActive() OVERRIDE {
+ return true; // always turned on
+ }
+ virtual TextInputType GetTextInputType() const OVERRIDE {
+ return text_input_client_ ? text_input_client_->GetTextInputType()
+ : TEXT_INPUT_TYPE_NONE;
+ }
+ virtual TextInputMode GetTextInputMode() const OVERRIDE {
+ return text_input_client_ ? text_input_client_->GetTextInputMode()
+ : TEXT_INPUT_MODE_DEFAULT;
+ }
+ virtual bool CanComposeInline() const OVERRIDE {
+ return text_input_client_ ? text_input_client_->CanComposeInline() : true;
+ }
+ virtual bool IsCandidatePopupOpen() const OVERRIDE {
+ return is_candidate_popup_open_;
+ }
+ virtual void AddObserver(InputMethodObserver* observer) OVERRIDE {
+ // not supported.
Seigo Nonaka 2013/11/18 20:00:27 If you will support this, please file a bug and le
yukawa 2013/11/19 07:17:51 I don't want to support this. IMHO, I'd like to d
+ }
+ virtual void RemoveObserver(InputMethodObserver* observer) OVERRIDE {
+ // not supported.
+ }
+
+ // Overridden from RemoteInputMethodPrivateWin:
+ virtual void SetRemoteDelegate(
+ internal::RemoteInputMethodDelegateWin* delegate) OVERRIDE{
+ remote_delegate_ = delegate;
+
+ // Sync initial state.
+ if (remote_delegate_) {
+ remote_delegate_->OnTextInputClientUpdated(
+ input_scopes_, composition_character_bounds_);
+ }
+ }
+ virtual void OnCandidatePopupChanged(bool visible) OVERRIDE {
+ is_candidate_popup_open_ = visible;
+ }
+ virtual void OnLanguageChanged(LANGID langid, bool /*is_ime*/) OVERRIDE {
+ // Note: Currently |is_ime| is not utilized yet.
+ const bool changed = (langid_ != langid);
+ langid_ = langid;
+ if (changed && GetTextInputClient())
+ GetTextInputClient()->OnInputMethodChanged();
+ }
+
+ bool CanSendRemoteNotification(
+ const TextInputClient* text_input_client) const {
+ return text_input_client_ &&
+ text_input_client_ == text_input_client &&
+ remote_delegate_;
+ }
+
+ internal::InputMethodDelegate* delegate_;
+ internal::RemoteInputMethodDelegateWin* remote_delegate_;
+
+ TextInputClient* text_input_client_;
+ std::vector<int32> input_scopes_;
+ std::vector<gfx::Rect> composition_character_bounds_;
+ bool is_candidate_popup_open_;
+ bool is_ime_;
+ LANGID langid_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteInputMethodWin);
+};
+
+} // namespace
+
+RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {}
+
+// static
+scoped_ptr<InputMethod> CreateRemoteInputMethodWin(
+ internal::InputMethodDelegate* delegate) {
+ return scoped_ptr<InputMethod>(new RemoteInputMethodWin(delegate));
+}
+
+// static
+RemoteInputMethodPrivateWin* RemoteInputMethodPrivateWin::Get(
+ InputMethod* input_method) {
+ return InstanceMapper::GetPrivate(input_method);
+}
+
+} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698