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

Unified Diff: win8/metro_driver/ime/text_service.cc

Issue 53553003: WIP: Ash IME support (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
« no previous file with comments | « win8/metro_driver/ime/text_service.h ('k') | win8/metro_driver/ime/text_store.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: win8/metro_driver/ime/text_service.cc
diff --git a/win8/metro_driver/ime/text_service.cc b/win8/metro_driver/ime/text_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4d1a4188f8476d675e443a65e9e4411512aa65ed
--- /dev/null
+++ b/win8/metro_driver/ime/text_service.cc
@@ -0,0 +1,252 @@
+// 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 "win8/metro_driver/ime/text_service.h"
+
+#include <inputscope.h>
+#include <msctf.h>
+
+#include "base/win/scoped_variant.h"
+#include "win8/metro_driver/ime/text_store.h"
+
+namespace metro_driver {
+namespace {
+
+class DocumentImpl {
+ public:
+ DocumentImpl()
+ : edit_cookie_(TF_INVALID_COOKIE),
+ text_edit_sink_cookie_(TF_INVALID_COOKIE) {}
+
+ ~DocumentImpl() {
+ Uninitialize();
+ }
+
+ bool Initialize(ITfThreadMgr2* thread_manager,
+ TfClientId client_id,
+ TextStore* text_store) {
+ Uninitialize();
+
+ base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
+ base::win::ScopedComPtr<ITfContext> context;
+
+ if (FAILED(thread_manager->CreateDocumentMgr(document_manager.Receive()))) {
+ return false;
+ }
+
+ DWORD edit_cookie = TF_INVALID_EDIT_COOKIE;
+ if (FAILED(document_manager->CreateContext(
+ client_id,
+ 0,
+ static_cast<ITextStoreACP*>(text_store),
+ context.Receive(),
+ &edit_cookie))) {
+ return false;
+ }
+
+ if (FAILED(document_manager->Push(context))) {
+ return false;
+ }
+
+ base::win::ScopedComPtr<ITfSource> source;
+ DWORD text_edit_sink_cookie = TF_INVALID_EDIT_COOKIE;
+ if (text_store) {
+ if (FAILED(source.QueryFrom(context))) {
+ return false;
+ }
+ if (FAILED(source->AdviseSink(IID_ITfTextEditSink,
+ static_cast<ITfTextEditSink*>(text_store),
+ &text_edit_sink_cookie))) {
+ return false;
+ }
+ }
+
+ document_manager_ = document_manager;
+ context_ = context;
+ text_store_ = text_store;
+ text_edit_sink_source_ = source;
+ edit_cookie_ = edit_cookie;
+ text_edit_sink_cookie_ = text_edit_sink_cookie;
+ return true;
+ }
+
+ void Uninitialize() {
+ if (text_edit_sink_source_ &&
+ (text_edit_sink_cookie_ != TF_INVALID_COOKIE)) {
+ text_edit_sink_source_->UnadviseSink(text_edit_sink_cookie_);
+ text_edit_sink_cookie_ = TF_INVALID_COOKIE;
+ text_edit_sink_source_.Release();
+ }
+ document_manager_.Release();
+
+ scoped_refptr<TextStore> text_store;
+ text_store_.swap(text_store);
+ }
+
+ ITfDocumentMgr* document_manager() const {
+ return document_manager_;
+ }
+
+ ITfContext* context() const {
+ return context_;
+ }
+
+ scoped_refptr<TextStore> text_store() {
+ return text_store_;
+ }
+
+ private:
+ base::win::ScopedComPtr<ITfDocumentMgr> document_manager_;
+ base::win::ScopedComPtr<ITfSource> text_edit_sink_source_;
+ base::win::ScopedComPtr<ITfContext> context_;
+ scoped_refptr<TextStore> text_store_;
+ DWORD edit_cookie_;
+ DWORD text_edit_sink_cookie_;
+
+ DISALLOW_COPY_AND_ASSIGN(DocumentImpl);
+};
+
+// Japanese IME expects the default value of this compartment is
+// TF_SENTENCEMODE_PHRASEPREDICT like IMM32 implementation. This value is
+// managed per thread, thus setting this value at once is enough. This
+// value never affects other IMEs except for Japanese.
+bool InitializeInputModeSentene(ITfThreadMgr2* thread_manager,
+ TfClientId client_id) {
+ base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager;
+ if (FAILED(thread_compartment_manager.QueryFrom(thread_manager)))
+ return false;
+
+ base::win::ScopedComPtr<ITfCompartment> sentence_compartment;
+ if (FAILED(thread_compartment_manager->GetCompartment(
+ GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE,
+ sentence_compartment.Receive())))
+ return false;
+
+ base::win::ScopedVariant sentence_variant;
+ sentence_variant.Set(TF_SENTENCEMODE_PHRASEPREDICT);
+ if (FAILED(sentence_compartment->SetValue(client_id, &sentence_variant)))
+ return false;
+ return true;
+}
+
+// Initializes |context| where an IME will be disabled.
+bool InitializeDisabledContext(ITfContext* context, TfClientId client_id) {
+ base::win::ScopedComPtr<ITfCompartmentMgr> compartment_mgr;
+ if (FAILED(compartment_mgr.QueryFrom(context)))
+ return false;
+
+ base::win::ScopedComPtr<ITfCompartment> disabled_compartment;
+ if (FAILED(compartment_mgr->GetCompartment(
+ GUID_COMPARTMENT_KEYBOARD_DISABLED,
+ disabled_compartment.Receive()))) {
+ return false;
+ }
+
+ base::win::ScopedVariant variant;
+ variant.Set(1);
+ if (FAILED(disabled_compartment->SetValue(client_id, &variant)))
+ return false;
+
+ base::win::ScopedComPtr<ITfCompartment> empty_context;
+ if (FAILED(compartment_mgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT,
+ empty_context.Receive()))) {
+ return false;
+ }
+
+ base::win::ScopedVariant empty_context_variant;
+ empty_context_variant.Set(static_cast<int32>(1));
+ if (FAILED(empty_context->SetValue(client_id, &empty_context_variant)))
+ return false;
+
+ return true;
+}
+
+} // namespace
+
+struct TextService::InternalState {
+ InternalState()
+ : client_id(TF_CLIENTID_NULL),
+ win_event_hook_initialized(false),
+ window_handle(NULL),
+ text_store_delegate(NULL) {}
+
+ TfClientId client_id;
+ bool win_event_hook_initialized;
+ scoped_ptr<DocumentImpl> current_document;
+ base::win::ScopedComPtr<ITfThreadMgr2> thread_manager;
+ HWND window_handle;
+ TextStoreDelegate* text_store_delegate;
+};
+
+TextService::TextService(HWND window_handle,
+ TextStoreDelegate* text_store_delegate)
+ : state_(new InternalState) {
+ if (FAILED(state_->thread_manager.CreateInstance(CLSID_TF_ThreadMgr)))
+ return;
+ if (FAILED(state_->thread_manager->ActivateEx(&state_->client_id, 0)))
+ return;
+ state_->window_handle = window_handle;
+ state_->text_store_delegate = text_store_delegate;
+ InitializeInputModeSentene(state_->thread_manager, state_->client_id);
+}
+
+TextService::~TextService() {
+ state_->current_document.reset(NULL);
+ state_->thread_manager->Deactivate();
+ state_.reset(NULL);
+}
+
+void TextService::CancelComposition() {
+ DocumentImpl* document = state_->current_document.get();
+ if (!document)
+ return;
+ TextStore* text_store = document->text_store();
+ if (!text_store)
+ return;
+ text_store->CancelComposition();
+}
+
+void TextService::OnDocumentTypeChanged(
+ const std::vector<int32>& input_scopes) {
+ state_->current_document.reset(new DocumentImpl);
+ TextStore* text_store = NULL;
+ if (!input_scopes.empty()) {
+ std::vector<InputScope> buffer(input_scopes.size());
+ for (size_t i = 0; i < input_scopes.size(); ++i)
+ buffer[i] = static_cast<InputScope>(input_scopes[i]);
+ text_store = new TextStore(
+ state_->window_handle, buffer, state_->text_store_delegate);
+ }
+ scoped_ptr<DocumentImpl> new_document(new DocumentImpl);
+ if (!new_document->Initialize(state_->thread_manager.get(),
+ state_->client_id,
+ text_store)) {
+ return;
+ }
+ const bool has_password_field =
+ std::find(input_scopes.begin(), input_scopes.end(), IS_PASSWORD) !=
+ input_scopes.end();
+ const bool use_disabled_context = input_scopes.empty() || has_password_field;
+ if (use_disabled_context &&
+ !InitializeDisabledContext(new_document->context(), state_->client_id)) {
+ return;
+ }
+ state_->current_document.swap(new_document);
+ if (FAILED(state_->thread_manager->SetFocus(
+ state_->current_document->document_manager()))) {
+ return;
+ }
+ return;
+}
+
+void TextService::OnWindowActivated() {
+ DocumentImpl* document = state_->current_document.get();
+ if (!document)
+ return;
+ if (FAILED(state_->thread_manager->SetFocus(document->document_manager())))
+ return;
+}
+
+} // namespace metro_driver
+
« no previous file with comments | « win8/metro_driver/ime/text_service.h ('k') | win8/metro_driver/ime/text_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698