OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "win8/metro_driver/ime/text_service.h" | 5 #include "win8/metro_driver/ime/text_service.h" |
6 | 6 |
7 #include <msctf.h> | 7 #include <msctf.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/win/scoped_variant.h" | 10 #include "base/win/scoped_variant.h" |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 } | 169 } |
170 | 170 |
171 // A class that manages the lifetime of the event callback registration. When | 171 // A class that manages the lifetime of the event callback registration. When |
172 // this object is destroyed, corresponding event callback will be unregistered. | 172 // this object is destroyed, corresponding event callback will be unregistered. |
173 class EventSink { | 173 class EventSink { |
174 public: | 174 public: |
175 EventSink(DWORD cookie, base::win::ScopedComPtr<ITfSource> source) | 175 EventSink(DWORD cookie, base::win::ScopedComPtr<ITfSource> source) |
176 : cookie_(cookie), | 176 : cookie_(cookie), |
177 source_(source) {} | 177 source_(source) {} |
178 ~EventSink() { | 178 ~EventSink() { |
179 if (!source_ || cookie_ != TF_INVALID_COOKIE) | 179 if (!source_.get() || cookie_ != TF_INVALID_COOKIE) |
180 return; | 180 return; |
181 source_->UnadviseSink(cookie_); | 181 source_->UnadviseSink(cookie_); |
182 cookie_ = TF_INVALID_COOKIE; | 182 cookie_ = TF_INVALID_COOKIE; |
183 source_.Release(); | 183 source_.Release(); |
184 } | 184 } |
185 | 185 |
186 private: | 186 private: |
187 DWORD cookie_; | 187 DWORD cookie_; |
188 base::win::ScopedComPtr<ITfSource> source_; | 188 base::win::ScopedComPtr<ITfSource> source_; |
189 DISALLOW_COPY_AND_ASSIGN(EventSink); | 189 DISALLOW_COPY_AND_ASSIGN(EventSink); |
(...skipping 21 matching lines...) Expand all Loading... | |
211 // are maintained. | 211 // are maintained. |
212 // - TextStore: a COM object that abstracts text buffer. This object is | 212 // - TextStore: a COM object that abstracts text buffer. This object is |
213 // actually implemented by us in text_store.cc | 213 // actually implemented by us in text_store.cc |
214 // - ITfDocumentMgr: a focusable unit in TSF. This object is implemented by | 214 // - ITfDocumentMgr: a focusable unit in TSF. This object is implemented by |
215 // TSF runtime and works as a container of TextStore. | 215 // TSF runtime and works as a container of TextStore. |
216 // - EventSink: an object that ensures that the event callback between | 216 // - EventSink: an object that ensures that the event callback between |
217 // TSF runtime and TextStore is unregistered when this object is destroyed. | 217 // TSF runtime and TextStore is unregistered when this object is destroyed. |
218 class DocumentBinding { | 218 class DocumentBinding { |
219 public: | 219 public: |
220 ~DocumentBinding() { | 220 ~DocumentBinding() { |
221 if (!document_manager_) | 221 if (!document_manager_.get()) |
222 return; | 222 return; |
223 document_manager_->Pop(TF_POPF_ALL); | 223 document_manager_->Pop(TF_POPF_ALL); |
224 } | 224 } |
225 | 225 |
226 static scoped_ptr<DocumentBinding> Create( | 226 static scoped_ptr<DocumentBinding> Create( |
227 ITfThreadMgr* thread_manager, | 227 ITfThreadMgr* thread_manager, |
228 TfClientId client_id, | 228 TfClientId client_id, |
229 const std::vector<InputScope>& input_scopes, | 229 const std::vector<InputScope>& input_scopes, |
230 HWND window_handle, | 230 HWND window_handle, |
231 TextStoreDelegate* delegate) { | 231 TextStoreDelegate* delegate) { |
232 base::win::ScopedComPtr<ITfDocumentMgr> document_manager; | 232 base::win::ScopedComPtr<ITfDocumentMgr> document_manager; |
233 HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); | 233 HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); |
234 if (FAILED(hr)) { | 234 if (FAILED(hr)) { |
235 LOG(ERROR) << "ITfThreadMgr::CreateDocumentMgr failed. hr = " << hr; | 235 LOG(ERROR) << "ITfThreadMgr::CreateDocumentMgr failed. hr = " << hr; |
236 return scoped_ptr<DocumentBinding>(); | 236 return scoped_ptr<DocumentBinding>(); |
237 } | 237 } |
238 | 238 |
239 // Note: In our IPC protocol, an empty |input_scopes| is used to indicate | 239 // Note: In our IPC protocol, an empty |input_scopes| is used to indicate |
240 // that an IME must be disabled in this context. In such case, we need not | 240 // that an IME must be disabled in this context. In such case, we need not |
241 // instantiate TextStore. | 241 // instantiate TextStore. |
242 const bool use_null_text_store = input_scopes.empty(); | 242 const bool use_null_text_store = input_scopes.empty(); |
243 | 243 |
244 scoped_refptr<TextStore> text_store; | 244 scoped_refptr<TextStore> text_store; |
245 if (!use_null_text_store) { | 245 if (!use_null_text_store) { |
246 text_store = TextStore::Create(window_handle, input_scopes, delegate); | 246 text_store = TextStore::Create(window_handle, input_scopes, delegate); |
247 if (!text_store) { | 247 if (!text_store.get()) { |
248 LOG(ERROR) << "Failed to create TextStore."; | 248 LOG(ERROR) << "Failed to create TextStore."; |
249 return scoped_ptr<DocumentBinding>(); | 249 return scoped_ptr<DocumentBinding>(); |
250 } | 250 } |
251 } | 251 } |
252 | 252 |
253 base::win::ScopedComPtr<ITfContext> context; | 253 base::win::ScopedComPtr<ITfContext> context; |
254 DWORD edit_cookie = TF_INVALID_EDIT_COOKIE; | 254 DWORD edit_cookie = TF_INVALID_EDIT_COOKIE; |
255 hr = document_manager->CreateContext( | 255 hr = document_manager->CreateContext( |
256 client_id, | 256 client_id, |
257 0, | 257 0, |
258 static_cast<ITextStoreACP*>(text_store.get()), | 258 static_cast<ITextStoreACP*>(text_store.get()), |
259 context.Receive(), | 259 context.Receive(), |
260 &edit_cookie); | 260 &edit_cookie); |
261 if (FAILED(hr)) { | 261 if (FAILED(hr)) { |
262 LOG(ERROR) << "ITfDocumentMgr::CreateContext failed. hr = " << hr; | 262 LOG(ERROR) << "ITfDocumentMgr::CreateContext failed. hr = " << hr; |
263 return scoped_ptr<DocumentBinding>(); | 263 return scoped_ptr<DocumentBinding>(); |
264 } | 264 } |
265 | 265 |
266 // If null-TextStore is used or |input_scopes| looks like a password field, | 266 // If null-TextStore is used or |input_scopes| looks like a password field, |
267 // set special properties to tell IMEs to be disabled. | 267 // set special properties to tell IMEs to be disabled. |
268 if ((use_null_text_store || IsPasswordField(input_scopes)) && | 268 if ((use_null_text_store || IsPasswordField(input_scopes)) && |
269 !InitializeDisabledContext(context, client_id)) { | 269 !InitializeDisabledContext(context.get(), client_id)) { |
270 LOG(ERROR) << "InitializeDisabledContext failed."; | 270 LOG(ERROR) << "InitializeDisabledContext failed."; |
271 return scoped_ptr<DocumentBinding>(); | 271 return scoped_ptr<DocumentBinding>(); |
272 } | 272 } |
273 | 273 |
274 scoped_ptr<EventSink> text_edit_sink; | 274 scoped_ptr<EventSink> text_edit_sink; |
275 if (!use_null_text_store) { | 275 if (!use_null_text_store) { |
276 text_edit_sink = CreateTextEditSink(context, text_store); | 276 text_edit_sink = CreateTextEditSink(context.get(), text_store.get()); |
277 if (!text_edit_sink) { | 277 if (!text_edit_sink) { |
278 LOG(ERROR) << "CreateTextEditSink failed."; | 278 LOG(ERROR) << "CreateTextEditSink failed."; |
279 return scoped_ptr<DocumentBinding>(); | 279 return scoped_ptr<DocumentBinding>(); |
280 } | 280 } |
281 } | 281 } |
282 hr = document_manager->Push(context); | 282 hr = document_manager->Push(context.get()); |
283 if (FAILED(hr)) { | 283 if (FAILED(hr)) { |
284 LOG(ERROR) << "ITfDocumentMgr::Push failed. hr = " << hr; | 284 LOG(ERROR) << "ITfDocumentMgr::Push failed. hr = " << hr; |
285 return scoped_ptr<DocumentBinding>(); | 285 return scoped_ptr<DocumentBinding>(); |
286 } | 286 } |
287 return scoped_ptr<DocumentBinding>( | 287 return scoped_ptr<DocumentBinding>( |
288 new DocumentBinding(text_store, | 288 new DocumentBinding(text_store, |
289 document_manager, | 289 document_manager, |
290 text_edit_sink.Pass())); | 290 text_edit_sink.Pass())); |
291 } | 291 } |
292 | 292 |
293 ITfDocumentMgr* document_manager() const { | 293 ITfDocumentMgr* document_manager() const { return document_manager_.get(); } |
294 return document_manager_; | |
295 } | |
296 | 294 |
297 scoped_refptr<TextStore> text_store() const { | 295 scoped_refptr<TextStore> text_store() const { |
298 return text_store_; | 296 return text_store_; |
299 } | 297 } |
300 | 298 |
301 private: | 299 private: |
302 DocumentBinding(scoped_refptr<TextStore> text_store, | 300 DocumentBinding(scoped_refptr<TextStore> text_store, |
303 base::win::ScopedComPtr<ITfDocumentMgr> document_manager, | 301 base::win::ScopedComPtr<ITfDocumentMgr> document_manager, |
304 scoped_ptr<EventSink> text_edit_sink) | 302 scoped_ptr<EventSink> text_edit_sink) |
305 : text_store_(text_store), | 303 : text_store_(text_store), |
(...skipping 13 matching lines...) Expand all Loading... | |
319 TextServiceImpl(ITfThreadMgr* thread_manager, | 317 TextServiceImpl(ITfThreadMgr* thread_manager, |
320 TfClientId client_id, | 318 TfClientId client_id, |
321 HWND window_handle, | 319 HWND window_handle, |
322 TextServiceDelegate* delegate) | 320 TextServiceDelegate* delegate) |
323 : client_id_(client_id), | 321 : client_id_(client_id), |
324 window_handle_(window_handle), | 322 window_handle_(window_handle), |
325 delegate_(delegate), | 323 delegate_(delegate), |
326 thread_manager_(thread_manager) { | 324 thread_manager_(thread_manager) { |
327 DCHECK_NE(TF_CLIENTID_NULL, client_id); | 325 DCHECK_NE(TF_CLIENTID_NULL, client_id); |
328 DCHECK(window_handle != NULL); | 326 DCHECK(window_handle != NULL); |
329 DCHECK(thread_manager_); | 327 DCHECK(thread_manager_.get()); |
330 } | 328 } |
331 virtual ~TextServiceImpl() { | 329 virtual ~TextServiceImpl() { |
332 thread_manager_->Deactivate(); | 330 thread_manager_->Deactivate(); |
333 } | 331 } |
334 | 332 |
335 private: | 333 private: |
336 // TextService overrides: | 334 // TextService overrides: |
337 virtual void CancelComposition() override { | 335 virtual void CancelComposition() override { |
338 if (!current_document_) { | 336 if (!current_document_) { |
339 VLOG(0) << "|current_document_| is NULL due to the previous error."; | 337 VLOG(0) << "|current_document_| is NULL due to the previous error."; |
340 return; | 338 return; |
341 } | 339 } |
342 TextStore* text_store = current_document_->text_store(); | 340 scoped_refptr<TextStore> text_store = current_document_->text_store(); |
343 if (!text_store) | 341 if (!text_store) |
grt (UTC plus 2)
2014/11/21 17:28:57
shouldn't this be:
if (!text_store.get())
?
dcheng
2014/11/21 17:35:20
Yeah, I didn't run the tool recursively. Usually I
| |
344 return; | 342 return; |
345 text_store->CancelComposition(); | 343 text_store->CancelComposition(); |
346 } | 344 } |
347 | 345 |
348 virtual void OnDocumentChanged( | 346 virtual void OnDocumentChanged( |
349 const std::vector<int32>& input_scopes, | 347 const std::vector<int32>& input_scopes, |
350 const std::vector<metro_viewer::CharacterBounds>& character_bounds) | 348 const std::vector<metro_viewer::CharacterBounds>& character_bounds) |
351 override { | 349 override { |
352 bool document_type_changed = input_scopes_ != input_scopes; | 350 bool document_type_changed = input_scopes_ != input_scopes; |
353 input_scopes_ = input_scopes; | 351 input_scopes_ = input_scopes; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " | 470 LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " |
473 << hr; | 471 << hr; |
474 return scoped_ptr<TextService>(); | 472 return scoped_ptr<TextService>(); |
475 } | 473 } |
476 TfClientId client_id = TF_CLIENTID_NULL; | 474 TfClientId client_id = TF_CLIENTID_NULL; |
477 hr = thread_manager->Activate(&client_id); | 475 hr = thread_manager->Activate(&client_id); |
478 if (FAILED(hr)) { | 476 if (FAILED(hr)) { |
479 LOG(ERROR) << "ITfThreadMgr::Activate failed. hr = " << hr; | 477 LOG(ERROR) << "ITfThreadMgr::Activate failed. hr = " << hr; |
480 return scoped_ptr<TextService>(); | 478 return scoped_ptr<TextService>(); |
481 } | 479 } |
482 if (!InitializeSentenceMode(thread_manager, client_id)) { | 480 if (!InitializeSentenceMode(thread_manager.get(), client_id)) { |
483 LOG(ERROR) << "InitializeSentenceMode failed."; | 481 LOG(ERROR) << "InitializeSentenceMode failed."; |
484 thread_manager->Deactivate(); | 482 thread_manager->Deactivate(); |
485 return scoped_ptr<TextService>(); | 483 return scoped_ptr<TextService>(); |
486 } | 484 } |
487 return scoped_ptr<TextService>(new TextServiceImpl(thread_manager, | 485 return scoped_ptr<TextService>(new TextServiceImpl( |
488 client_id, | 486 thread_manager.get(), client_id, window_handle, delegate)); |
489 window_handle, | |
490 delegate)); | |
491 } | 487 } |
492 | 488 |
493 } // namespace metro_driver | 489 } // namespace metro_driver |
OLD | NEW |