| Index: win8/metro_driver/ime/language_profile_monitor.cc
|
| diff --git a/win8/metro_driver/ime/language_profile_monitor.cc b/win8/metro_driver/ime/language_profile_monitor.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6f0ae5caf22895340fac0e5d91676669f65e1aaa
|
| --- /dev/null
|
| +++ b/win8/metro_driver/ime/language_profile_monitor.cc
|
| @@ -0,0 +1,149 @@
|
| +// 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/language_profile_monitor.h"
|
| +
|
| +#include <msctf.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/win/scoped_comptr.h"
|
| +#include "win8/metro_driver/ime/language_profile_observer.h"
|
| +
|
| +namespace metro_driver {
|
| +namespace {
|
| +
|
| +class LanguageProfileMonitor;
|
| +LanguageProfileMonitor* g_monitor = NULL;
|
| +LanguageProfileObserver* g_observer_ = NULL;
|
| +
|
| +class LanguageProfileMonitor : public ITfLanguageProfileNotifySink {
|
| + public:
|
| + static LanguageProfileMonitor* Create() {
|
| + base::win::ScopedComPtr<ITfInputProcessorProfiles> profiles;
|
| + if (FAILED(profiles.CreateInstance(CLSID_TF_InputProcessorProfiles)))
|
| + return NULL;
|
| + base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager;
|
| + if (FAILED(profile_manager.QueryFrom(profiles)))
|
| + return NULL;
|
| + base::win::ScopedComPtr<ITfSource> profiles_source;
|
| + if (FAILED(profiles_source.QueryFrom(profiles)))
|
| + return NULL;
|
| +
|
| + LanguageProfileMonitor* obj = new LanguageProfileMonitor(profile_manager);
|
| +
|
| + DWORD cookie = TF_INVALID_COOKIE;
|
| + if (FAILED(profiles_source->AdviseSink(IID_ITfLanguageProfileNotifySink,
|
| + obj,
|
| + &cookie))) {
|
| + obj->AddRef();
|
| + obj->Release();
|
| + return NULL;
|
| + }
|
| +
|
| + obj->OnAdvise(profiles_source, cookie);
|
| + return obj;
|
| + }
|
| +
|
| + void Unadvise() {
|
| + if (cookie_ == TF_INVALID_COOKIE || !source_)
|
| + return;
|
| + if (FAILED(source_->UnadviseSink(cookie_)))
|
| + return;
|
| + cookie_ = TF_INVALID_COOKIE;
|
| + source_.Release();
|
| + }
|
| +
|
| + // IUnknown overrides:
|
| + STDMETHOD_(ULONG, AddRef)() OVERRIDE{
|
| + return ::InterlockedIncrement(&ref_count_);
|
| + }
|
| + STDMETHOD_(ULONG, Release)() OVERRIDE {
|
| + const LONG count = ::InterlockedDecrement(&ref_count_);
|
| + if (!count) {
|
| + delete this;
|
| + return 0;
|
| + }
|
| + return static_cast<ULONG>(count);
|
| + }
|
| + STDMETHOD(QueryInterface)(REFIID iid, void** result) OVERRIDE {
|
| + if (!result)
|
| + return E_INVALIDARG;
|
| + if (iid == IID_IUnknown) {
|
| + *result = static_cast<IUnknown*>(this);
|
| + } else if (iid == IID_ITfLanguageProfileNotifySink) {
|
| + *result = static_cast<ITfLanguageProfileNotifySink*>(this);
|
| + } else {
|
| + *result = NULL;
|
| + return E_NOINTERFACE;
|
| + }
|
| + AddRef();
|
| + return S_OK;
|
| + }
|
| +
|
| + private:
|
| + LanguageProfileMonitor(ITfInputProcessorProfileMgr* profile_manager)
|
| + : ref_count_(0),
|
| + profile_manager_(profile_manager) {
|
| + }
|
| +
|
| + // ITfLanguageProfileNotifySink overrides:
|
| + STDMETHOD(OnLanguageChange)(LANGID langid, BOOL *accept) OVERRIDE {
|
| + if (!accept)
|
| + return E_INVALIDARG;
|
| + *accept = TRUE;
|
| + return S_OK;
|
| + }
|
| + STDMETHOD(OnLanguageChanged)() OVERRIDE{
|
| + TF_INPUTPROCESSORPROFILE profile = {};
|
| + if (FAILED(profile_manager_->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD,
|
| + &profile))) {
|
| + return S_OK;
|
| + }
|
| + if (!g_observer_)
|
| + return S_OK;
|
| + g_observer_->OnInputSourceChanged(
|
| + profile.langid,
|
| + profile.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR);
|
| + return S_OK;
|
| + }
|
| +
|
| + void OnAdvise(ITfSource* source, DWORD cookie) {
|
| + source_ = source;
|
| + cookie_ = cookie;
|
| + }
|
| +
|
| + volatile LONG ref_count_;
|
| +
|
| + base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager_;
|
| + base::win::ScopedComPtr<ITfSource> source_;
|
| + DWORD cookie_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(LanguageProfileMonitor);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +void AddLanguageProfileObserver(LanguageProfileObserver* observer) {
|
| + CHECK(g_observer_ == NULL);
|
| + g_observer_ = observer;
|
| +
|
| + g_monitor = LanguageProfileMonitor::Create();
|
| + if (g_monitor)
|
| + g_monitor->AddRef();
|
| +}
|
| +
|
| +void RemoveLanguageProfileObserver(LanguageProfileObserver* observer) {
|
| + if (g_observer_ != observer)
|
| + return;
|
| + g_observer_ = NULL;
|
| + if (!g_monitor)
|
| + return;
|
| + g_monitor->Unadvise();
|
| + g_monitor->Release();
|
| + g_monitor = NULL;
|
| +}
|
| +
|
| +} // namespace metro_driver
|
| +
|
|
|