OLD | NEW |
(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/language_profile_monitor.h" |
| 6 |
| 7 #include <msctf.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/win/scoped_comptr.h" |
| 12 #include "win8/metro_driver/ime/language_profile_observer.h" |
| 13 |
| 14 namespace metro_driver { |
| 15 namespace { |
| 16 |
| 17 class LanguageProfileMonitor; |
| 18 LanguageProfileMonitor* g_monitor = NULL; |
| 19 LanguageProfileObserver* g_observer_ = NULL; |
| 20 |
| 21 class LanguageProfileMonitor : public ITfLanguageProfileNotifySink { |
| 22 public: |
| 23 static LanguageProfileMonitor* Create() { |
| 24 base::win::ScopedComPtr<ITfInputProcessorProfiles> profiles; |
| 25 if (FAILED(profiles.CreateInstance(CLSID_TF_InputProcessorProfiles))) |
| 26 return NULL; |
| 27 base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager; |
| 28 if (FAILED(profile_manager.QueryFrom(profiles))) |
| 29 return NULL; |
| 30 base::win::ScopedComPtr<ITfSource> profiles_source; |
| 31 if (FAILED(profiles_source.QueryFrom(profiles))) |
| 32 return NULL; |
| 33 |
| 34 LanguageProfileMonitor* obj = new LanguageProfileMonitor(profile_manager); |
| 35 |
| 36 DWORD cookie = TF_INVALID_COOKIE; |
| 37 if (FAILED(profiles_source->AdviseSink(IID_ITfLanguageProfileNotifySink, |
| 38 obj, |
| 39 &cookie))) { |
| 40 obj->AddRef(); |
| 41 obj->Release(); |
| 42 return NULL; |
| 43 } |
| 44 |
| 45 obj->OnAdvise(profiles_source, cookie); |
| 46 return obj; |
| 47 } |
| 48 |
| 49 void Unadvise() { |
| 50 if (cookie_ == TF_INVALID_COOKIE || !source_) |
| 51 return; |
| 52 if (FAILED(source_->UnadviseSink(cookie_))) |
| 53 return; |
| 54 cookie_ = TF_INVALID_COOKIE; |
| 55 source_.Release(); |
| 56 } |
| 57 |
| 58 // IUnknown overrides: |
| 59 STDMETHOD_(ULONG, AddRef)() OVERRIDE{ |
| 60 return ::InterlockedIncrement(&ref_count_); |
| 61 } |
| 62 STDMETHOD_(ULONG, Release)() OVERRIDE { |
| 63 const LONG count = ::InterlockedDecrement(&ref_count_); |
| 64 if (!count) { |
| 65 delete this; |
| 66 return 0; |
| 67 } |
| 68 return static_cast<ULONG>(count); |
| 69 } |
| 70 STDMETHOD(QueryInterface)(REFIID iid, void** result) OVERRIDE { |
| 71 if (!result) |
| 72 return E_INVALIDARG; |
| 73 if (iid == IID_IUnknown) { |
| 74 *result = static_cast<IUnknown*>(this); |
| 75 } else if (iid == IID_ITfLanguageProfileNotifySink) { |
| 76 *result = static_cast<ITfLanguageProfileNotifySink*>(this); |
| 77 } else { |
| 78 *result = NULL; |
| 79 return E_NOINTERFACE; |
| 80 } |
| 81 AddRef(); |
| 82 return S_OK; |
| 83 } |
| 84 |
| 85 private: |
| 86 LanguageProfileMonitor(ITfInputProcessorProfileMgr* profile_manager) |
| 87 : ref_count_(0), |
| 88 profile_manager_(profile_manager) { |
| 89 } |
| 90 |
| 91 // ITfLanguageProfileNotifySink overrides: |
| 92 STDMETHOD(OnLanguageChange)(LANGID langid, BOOL *accept) OVERRIDE { |
| 93 if (!accept) |
| 94 return E_INVALIDARG; |
| 95 *accept = TRUE; |
| 96 return S_OK; |
| 97 } |
| 98 STDMETHOD(OnLanguageChanged)() OVERRIDE{ |
| 99 TF_INPUTPROCESSORPROFILE profile = {}; |
| 100 if (FAILED(profile_manager_->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD, |
| 101 &profile))) { |
| 102 return S_OK; |
| 103 } |
| 104 if (!g_observer_) |
| 105 return S_OK; |
| 106 g_observer_->OnInputSourceChanged( |
| 107 profile.langid, |
| 108 profile.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR); |
| 109 return S_OK; |
| 110 } |
| 111 |
| 112 void OnAdvise(ITfSource* source, DWORD cookie) { |
| 113 source_ = source; |
| 114 cookie_ = cookie; |
| 115 } |
| 116 |
| 117 volatile LONG ref_count_; |
| 118 |
| 119 base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager_; |
| 120 base::win::ScopedComPtr<ITfSource> source_; |
| 121 DWORD cookie_; |
| 122 |
| 123 DISALLOW_COPY_AND_ASSIGN(LanguageProfileMonitor); |
| 124 }; |
| 125 |
| 126 } // namespace |
| 127 |
| 128 void AddLanguageProfileObserver(LanguageProfileObserver* observer) { |
| 129 CHECK(g_observer_ == NULL); |
| 130 g_observer_ = observer; |
| 131 |
| 132 g_monitor = LanguageProfileMonitor::Create(); |
| 133 if (g_monitor) |
| 134 g_monitor->AddRef(); |
| 135 } |
| 136 |
| 137 void RemoveLanguageProfileObserver(LanguageProfileObserver* observer) { |
| 138 if (g_observer_ != observer) |
| 139 return; |
| 140 g_observer_ = NULL; |
| 141 if (!g_monitor) |
| 142 return; |
| 143 g_monitor->Unadvise(); |
| 144 g_monitor->Release(); |
| 145 g_monitor = NULL; |
| 146 } |
| 147 |
| 148 } // namespace metro_driver |
| 149 |
OLD | NEW |