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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "win8/metro_driver/ime/text_service.h"
6
7 #include <inputscope.h>
8 #include <msctf.h>
9
10 #include "base/win/scoped_variant.h"
11 #include "win8/metro_driver/ime/text_store.h"
12
13 namespace metro_driver {
14 namespace {
15
16 class DocumentImpl {
17 public:
18 DocumentImpl()
19 : edit_cookie_(TF_INVALID_COOKIE),
20 text_edit_sink_cookie_(TF_INVALID_COOKIE) {}
21
22 ~DocumentImpl() {
23 Uninitialize();
24 }
25
26 bool Initialize(ITfThreadMgr2* thread_manager,
27 TfClientId client_id,
28 TextStore* text_store) {
29 Uninitialize();
30
31 base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
32 base::win::ScopedComPtr<ITfContext> context;
33
34 if (FAILED(thread_manager->CreateDocumentMgr(document_manager.Receive()))) {
35 return false;
36 }
37
38 DWORD edit_cookie = TF_INVALID_EDIT_COOKIE;
39 if (FAILED(document_manager->CreateContext(
40 client_id,
41 0,
42 static_cast<ITextStoreACP*>(text_store),
43 context.Receive(),
44 &edit_cookie))) {
45 return false;
46 }
47
48 if (FAILED(document_manager->Push(context))) {
49 return false;
50 }
51
52 base::win::ScopedComPtr<ITfSource> source;
53 DWORD text_edit_sink_cookie = TF_INVALID_EDIT_COOKIE;
54 if (text_store) {
55 if (FAILED(source.QueryFrom(context))) {
56 return false;
57 }
58 if (FAILED(source->AdviseSink(IID_ITfTextEditSink,
59 static_cast<ITfTextEditSink*>(text_store),
60 &text_edit_sink_cookie))) {
61 return false;
62 }
63 }
64
65 document_manager_ = document_manager;
66 context_ = context;
67 text_store_ = text_store;
68 text_edit_sink_source_ = source;
69 edit_cookie_ = edit_cookie;
70 text_edit_sink_cookie_ = text_edit_sink_cookie;
71 return true;
72 }
73
74 void Uninitialize() {
75 if (text_edit_sink_source_ &&
76 (text_edit_sink_cookie_ != TF_INVALID_COOKIE)) {
77 text_edit_sink_source_->UnadviseSink(text_edit_sink_cookie_);
78 text_edit_sink_cookie_ = TF_INVALID_COOKIE;
79 text_edit_sink_source_.Release();
80 }
81 document_manager_.Release();
82
83 scoped_refptr<TextStore> text_store;
84 text_store_.swap(text_store);
85 }
86
87 ITfDocumentMgr* document_manager() const {
88 return document_manager_;
89 }
90
91 ITfContext* context() const {
92 return context_;
93 }
94
95 scoped_refptr<TextStore> text_store() {
96 return text_store_;
97 }
98
99 private:
100 base::win::ScopedComPtr<ITfDocumentMgr> document_manager_;
101 base::win::ScopedComPtr<ITfSource> text_edit_sink_source_;
102 base::win::ScopedComPtr<ITfContext> context_;
103 scoped_refptr<TextStore> text_store_;
104 DWORD edit_cookie_;
105 DWORD text_edit_sink_cookie_;
106
107 DISALLOW_COPY_AND_ASSIGN(DocumentImpl);
108 };
109
110 // Japanese IME expects the default value of this compartment is
111 // TF_SENTENCEMODE_PHRASEPREDICT like IMM32 implementation. This value is
112 // managed per thread, thus setting this value at once is enough. This
113 // value never affects other IMEs except for Japanese.
114 bool InitializeInputModeSentene(ITfThreadMgr2* thread_manager,
115 TfClientId client_id) {
116 base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager;
117 if (FAILED(thread_compartment_manager.QueryFrom(thread_manager)))
118 return false;
119
120 base::win::ScopedComPtr<ITfCompartment> sentence_compartment;
121 if (FAILED(thread_compartment_manager->GetCompartment(
122 GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE,
123 sentence_compartment.Receive())))
124 return false;
125
126 base::win::ScopedVariant sentence_variant;
127 sentence_variant.Set(TF_SENTENCEMODE_PHRASEPREDICT);
128 if (FAILED(sentence_compartment->SetValue(client_id, &sentence_variant)))
129 return false;
130 return true;
131 }
132
133 // Initializes |context| where an IME will be disabled.
134 bool InitializeDisabledContext(ITfContext* context, TfClientId client_id) {
135 base::win::ScopedComPtr<ITfCompartmentMgr> compartment_mgr;
136 if (FAILED(compartment_mgr.QueryFrom(context)))
137 return false;
138
139 base::win::ScopedComPtr<ITfCompartment> disabled_compartment;
140 if (FAILED(compartment_mgr->GetCompartment(
141 GUID_COMPARTMENT_KEYBOARD_DISABLED,
142 disabled_compartment.Receive()))) {
143 return false;
144 }
145
146 base::win::ScopedVariant variant;
147 variant.Set(1);
148 if (FAILED(disabled_compartment->SetValue(client_id, &variant)))
149 return false;
150
151 base::win::ScopedComPtr<ITfCompartment> empty_context;
152 if (FAILED(compartment_mgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT,
153 empty_context.Receive()))) {
154 return false;
155 }
156
157 base::win::ScopedVariant empty_context_variant;
158 empty_context_variant.Set(static_cast<int32>(1));
159 if (FAILED(empty_context->SetValue(client_id, &empty_context_variant)))
160 return false;
161
162 return true;
163 }
164
165 } // namespace
166
167 struct TextService::InternalState {
168 InternalState()
169 : client_id(TF_CLIENTID_NULL),
170 win_event_hook_initialized(false),
171 window_handle(NULL),
172 text_store_delegate(NULL) {}
173
174 TfClientId client_id;
175 bool win_event_hook_initialized;
176 scoped_ptr<DocumentImpl> current_document;
177 base::win::ScopedComPtr<ITfThreadMgr2> thread_manager;
178 HWND window_handle;
179 TextStoreDelegate* text_store_delegate;
180 };
181
182 TextService::TextService(HWND window_handle,
183 TextStoreDelegate* text_store_delegate)
184 : state_(new InternalState) {
185 if (FAILED(state_->thread_manager.CreateInstance(CLSID_TF_ThreadMgr)))
186 return;
187 if (FAILED(state_->thread_manager->ActivateEx(&state_->client_id, 0)))
188 return;
189 state_->window_handle = window_handle;
190 state_->text_store_delegate = text_store_delegate;
191 InitializeInputModeSentene(state_->thread_manager, state_->client_id);
192 }
193
194 TextService::~TextService() {
195 state_->current_document.reset(NULL);
196 state_->thread_manager->Deactivate();
197 state_.reset(NULL);
198 }
199
200 void TextService::CancelComposition() {
201 DocumentImpl* document = state_->current_document.get();
202 if (!document)
203 return;
204 TextStore* text_store = document->text_store();
205 if (!text_store)
206 return;
207 text_store->CancelComposition();
208 }
209
210 void TextService::OnDocumentTypeChanged(
211 const std::vector<int32>& input_scopes) {
212 state_->current_document.reset(new DocumentImpl);
213 TextStore* text_store = NULL;
214 if (!input_scopes.empty()) {
215 std::vector<InputScope> buffer(input_scopes.size());
216 for (size_t i = 0; i < input_scopes.size(); ++i)
217 buffer[i] = static_cast<InputScope>(input_scopes[i]);
218 text_store = new TextStore(
219 state_->window_handle, buffer, state_->text_store_delegate);
220 }
221 scoped_ptr<DocumentImpl> new_document(new DocumentImpl);
222 if (!new_document->Initialize(state_->thread_manager.get(),
223 state_->client_id,
224 text_store)) {
225 return;
226 }
227 const bool has_password_field =
228 std::find(input_scopes.begin(), input_scopes.end(), IS_PASSWORD) !=
229 input_scopes.end();
230 const bool use_disabled_context = input_scopes.empty() || has_password_field;
231 if (use_disabled_context &&
232 !InitializeDisabledContext(new_document->context(), state_->client_id)) {
233 return;
234 }
235 state_->current_document.swap(new_document);
236 if (FAILED(state_->thread_manager->SetFocus(
237 state_->current_document->document_manager()))) {
238 return;
239 }
240 return;
241 }
242
243 void TextService::OnWindowActivated() {
244 DocumentImpl* document = state_->current_document.get();
245 if (!document)
246 return;
247 if (FAILED(state_->thread_manager->SetFocus(document->document_manager())))
248 return;
249 }
250
251 } // namespace metro_driver
252
OLDNEW
« 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