Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/widget/windows/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 25 kB image not shown  

Quelle  TSFStaticSink.cpp   Sprache: C

 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "TSFStaticSink.h"

#include "TSFTextStore.h"
#include "TSFUtils.h"
#include "WinIMEHandler.h"
#include "WinMessages.h"
#include "mozilla/Assertions.h"
#include "mozilla/Logging.h"
#include "mozilla/glean/WidgetWindowsMetrics.h"

#include <comutil.h>  // for _bstr_t
#include <oleauto.h>  // for SysAllocString
#include <olectl.h>

extern mozilla::LazyLogModule gIMELog;  // defined in TSFUtils.cpp

namespace mozilla::widget {

StaticRefPtr<TSFStaticSink> TSFStaticSink::sInstance;

// static
TSFStaticSink* TSFStaticSink::GetInstance() {
  if (!sInstance) {
    const RefPtr<ITfThreadMgr> threadMgr = TSFUtils::GetThreadMgr();
    if (NS_WARN_IF(!threadMgr)) {
      MOZ_LOG(
          gIMELog, LogLevel::Error,
          ("TSFStaticSink::GetInstance() FAILED to initialize TSFStaticSink "
           "instance due to no ThreadMgr instance"));
      return nullptr;
    }
    const RefPtr<ITfInputProcessorProfiles> inputProcessorProfiles =
        TSFUtils::GetInputProcessorProfiles();
    if (NS_WARN_IF(!inputProcessorProfiles)) {
      MOZ_LOG(
          gIMELog, LogLevel::Error,
          ("TSFStaticSink::GetInstance() FAILED to initialize TSFStaticSink "
           "instance due to no InputProcessorProfiles instance"));
      return nullptr;
    }
    RefPtr<TSFStaticSink> staticSink = new TSFStaticSink();
    if (NS_WARN_IF(!staticSink->Init(threadMgr, inputProcessorProfiles))) {
      staticSink->Destroy();
      MOZ_LOG(
          gIMELog, LogLevel::Error,
          ("TSFStaticSink::GetInstance() FAILED to initialize TSFStaticSink "
           "instance"));
      return nullptr;
    }
    sInstance = staticSink.forget();
  }
  return sInstance;
}

// static
bool TSFStaticSink::GetActiveTIPNameForTelemetry(nsAString& aName) {
  if (!sInstance || !sInstance->EnsureInitActiveTIPKeyboard()) {
    return false;
  }
  if (sInstance->mActiveTIPGUID == GUID_NULL) {
    aName.Truncate();
    aName.AppendPrintf("0x%04X", sInstance->mLangID);
    return true;
  }
  // key should be "LocaleID|Description".  Although GUID of the
  // profile is unique key since description may be localized for system
  // language, unfortunately, it's too long to record as key with its
  // description.  Therefore, we should record only the description with
  // LocaleID because Microsoft IME may not include language information.
  // 72 is kMaximumKeyStringLength in TelemetryScalar.cpp
  aName.Truncate();
  aName.AppendPrintf("0x%04X|", sInstance->mLangID);
  nsAutoString description;
  description.Assign(sInstance->mActiveTIPKeyboardDescription);
  static const uint32_t kMaxDescriptionLength = 72 - aName.Length();
  if (description.Length() > kMaxDescriptionLength) {
    if (NS_IS_LOW_SURROGATE(description[kMaxDescriptionLength - 1]) &&
        NS_IS_HIGH_SURROGATE(description[kMaxDescriptionLength - 2])) {
      description.Truncate(kMaxDescriptionLength - 2);
    } else {
      description.Truncate(kMaxDescriptionLength - 1);
    }
    // U+2026 is "..."
    description.Append(char16_t(0x2026));
  }
  aName.Append(description);
  return true;
}

// static
bool TSFStaticSink::IsMSChangJieOrMSQuickActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if the language
  // for current TIP is Traditional Chinese.
  if (!IsTraditionalChinese()) {
    return false;
  }
  switch (ActiveTIP()) {
    case TextInputProcessorID::MicrosoftChangJie:
    case TextInputProcessorID::MicrosoftQuick:
      return true;
    default:
      return false;
  }
}

// static
bool TSFStaticSink::IsMSPinyinOrMSWubiActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if the language
  // for current TIP is Simplified Chinese.
  if (!IsSimplifiedChinese()) {
    return false;
  }
  switch (ActiveTIP()) {
    case TextInputProcessorID::MicrosoftPinyin:
    case TextInputProcessorID::MicrosoftWubi:
      return true;
    default:
      return false;
  }
}

// static
bool TSFStaticSink::IsMSJapaneseIMEActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if the language
  // for current TIP is Japanese.
  if (!IsJapanese()) {
    return false;
  }
  return ActiveTIP() == TextInputProcessorID::MicrosoftIMEForJapanese;
}

// static
bool TSFStaticSink::IsGoogleJapaneseInputActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if the language
  // for current TIP is Japanese.
  if (!IsJapanese()) {
    return false;
  }
  return ActiveTIP() == TextInputProcessorID::GoogleJapaneseInput;
}

// static
bool TSFStaticSink::IsATOKActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if active TIP is
  // ATOK first since it's cheaper.
  return IsJapanese() && sInstance->IsATOKActiveInternal();
}

// static
bool TSFStaticSink::IsATOKReferringNativeCaretActive() {
  // ActiveTIP() is expensive if it hasn't computed active TIP yet.
  // For avoiding unnecessary computation, we should check if active TIP is
  // ATOK first since it's cheaper.
  if (!IsJapanese() || !sInstance->IsATOKActiveInternal()) {
    return false;
  }
  switch (ActiveTIP()) {
    case TextInputProcessorID::ATOK2011:
    case TextInputProcessorID::ATOK2012:
    case TextInputProcessorID::ATOK2013:
    case TextInputProcessorID::ATOK2014:
    case TextInputProcessorID::ATOK2015:
      return true;
    default:
      return false;
  }
}

bool TSFStaticSink::IsATOKActiveInternal() {
  EnsureInitActiveTIPKeyboard();
  // FYI: Name of packaged ATOK includes the release year like "ATOK 2015".
  //      Name of ATOK Passport (subscription) equals "ATOK".
  return StringBeginsWith(mActiveTIPKeyboardDescription, u"ATOK "_ns) ||
         mActiveTIPKeyboardDescription.EqualsLiteral("ATOK");
}

bool TSFStaticSink::IsSogouActive() {
  return IsSimplifiedChinese() && ActiveTIP() == TextInputProcessorID::Sogou;
}

bool TSFStaticSink::IsWeChatIMEActive() {
  return IsSimplifiedChinese() && ActiveTIP() == TextInputProcessorID::WeChat;
}

void TSFStaticSink::ComputeActiveTextInputProcessor() {
  if (mActiveTIP != TextInputProcessorID::NotComputed) {
    return;
  }

  if (mActiveTIPGUID == GUID_NULL) {
    mActiveTIP = TextInputProcessorID::None;
    return;
  }

  // Comparing GUID is slow. So, we should use language information to
  // reduce the comparing cost for TIP which is not we do not support
  // specifically since they are always compared with all supported TIPs.
  switch (mLangID) {
    case 0x0404:
      mActiveTIP = ComputeActiveTIPAsTraditionalChinese();
      break;
    case 0x0411:
      mActiveTIP = ComputeActiveTIPAsJapanese();
      break;
    case 0x0412:
      mActiveTIP = ComputeActiveTIPAsKorean();
      break;
    case 0x0804:
      mActiveTIP = ComputeActiveTIPAsSimplifiedChinese();
      break;
    default:
      mActiveTIP = TextInputProcessorID::Unknown;
      break;
  }
  // Special case for Keyman Desktop, it is available for any languages.
  // Therefore, we need to check it only if we don't know the active TIP.
  if (mActiveTIP != TextInputProcessorID::Unknown) {
    return;
  }

  // Note that keyboard layouts for Keyman assign its GUID on install
  // randomly, but CLSID is constant in any environments.
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1670834#c7
  // https://github.com/keymanapp/keyman/blob/318c73a9e1d571d942837ff9964590626e5bd5aa/windows/src/engine/kmtip/globals.cpp#L37
  // {FE0420F1-38D1-4B4C-96BF-E7E20A74CFB7}
  static constexpr CLSID kKeymanDesktop_CLSID = {
      0xFE0420F1,
      0x38D1,
      0x4B4C,
      {0x96, 0xBF, 0xE7, 0xE2, 0x0A, 0x74, 0xCF, 0xB7}};
  if (mActiveTIPCLSID == kKeymanDesktop_CLSID) {
    mActiveTIP = TextInputProcessorID::KeymanDesktop;
  }
}

TextInputProcessorID TSFStaticSink::ComputeActiveTIPAsJapanese() {
  // {A76C93D9-5523-4E90-AAFA-4DB112F9AC76} (Win7, Win8.1, Win10)
  static constexpr GUID kMicrosoftIMEForJapaneseGUID = {
      0xA76C93D9,
      0x5523,
      0x4E90,
      {0xAA, 0xFA, 0x4D, 0xB1, 0x12, 0xF9, 0xAC, 0x76}};
  if (mActiveTIPGUID == kMicrosoftIMEForJapaneseGUID) {
    return TextInputProcessorID::MicrosoftIMEForJapanese;
  }
  // {54EDCC94-1524-4BB1-9FB7-7BABE4F4CA64}
  static constexpr GUID kMicrosoftOfficeIME2010ForJapaneseGUID = {
      0x54EDCC94,
      0x1524,
      0x4BB1,
      {0x9F, 0xB7, 0x7B, 0xAB, 0xE4, 0xF4, 0xCA, 0x64}};
  if (mActiveTIPGUID == kMicrosoftOfficeIME2010ForJapaneseGUID) {
    return TextInputProcessorID::MicrosoftOfficeIME2010ForJapanese;
  }
  // {773EB24E-CA1D-4B1B-B420-FA985BB0B80D}
  static constexpr GUID kGoogleJapaneseInputGUID = {
      0x773EB24E,
      0xCA1D,
      0x4B1B,
      {0xB4, 0x20, 0xFA, 0x98, 0x5B, 0xB0, 0xB8, 0x0D}};
  if (mActiveTIPGUID == kGoogleJapaneseInputGUID) {
    return TextInputProcessorID::GoogleJapaneseInput;
  }
  // {F9C24A5C-8A53-499D-9572-93B2FF582115}
  static const GUID kATOK2011GUID = {
      0xF9C24A5C,
      0x8A53,
      0x499D,
      {0x95, 0x72, 0x93, 0xB2, 0xFF, 0x58, 0x21, 0x15}};
  if (mActiveTIPGUID == kATOK2011GUID) {
    return TextInputProcessorID::ATOK2011;
  }
  // {1DE01562-F445-401B-B6C3-E5B18DB79461}
  static constexpr GUID kATOK2012GUID = {
      0x1DE01562,
      0xF445,
      0x401B,
      {0xB6, 0xC3, 0xE5, 0xB1, 0x8D, 0xB7, 0x94, 0x61}};
  if (mActiveTIPGUID == kATOK2012GUID) {
    return TextInputProcessorID::ATOK2012;
  }
  // {3C4DB511-189A-4168-B6EA-BFD0B4C85615}
  static constexpr GUID kATOK2013GUID = {
      0x3C4DB511,
      0x189A,
      0x4168,
      {0xB6, 0xEA, 0xBF, 0xD0, 0xB4, 0xC8, 0x56, 0x15}};
  if (mActiveTIPGUID == kATOK2013GUID) {
    return TextInputProcessorID::ATOK2013;
  }
  // {4EF33B79-6AA9-4271-B4BF-9321C279381B}
  static constexpr GUID kATOK2014GUID = {
      0x4EF33B79,
      0x6AA9,
      0x4271,
      {0xB4, 0xBF, 0x93, 0x21, 0xC2, 0x79, 0x38, 0x1B}};
  if (mActiveTIPGUID == kATOK2014GUID) {
    return TextInputProcessorID::ATOK2014;
  }
  // {EAB4DC00-CE2E-483D-A86A-E6B99DA9599A}
  static constexpr GUID kATOK2015GUID = {
      0xEAB4DC00,
      0xCE2E,
      0x483D,
      {0xA8, 0x6A, 0xE6, 0xB9, 0x9D, 0xA9, 0x59, 0x9A}};
  if (mActiveTIPGUID == kATOK2015GUID) {
    return TextInputProcessorID::ATOK2015;
  }
  // {0B557B4C-5740-4110-A60A-1493FA10BF2B}
  static constexpr GUID kATOK2016GUID = {
      0x0B557B4C,
      0x5740,
      0x4110,
      {0xA6, 0x0A, 0x14, 0x93, 0xFA, 0x10, 0xBF, 0x2B}};
  if (mActiveTIPGUID == kATOK2016GUID) {
    return TextInputProcessorID::ATOK2016;
  }

  // * ATOK 2017
  //   - {6DBFD8F5-701D-11E6-920F-782BCBA6348F}
  // * ATOK Passport (confirmed with version 31.1.2)
  //   - {A38F2FD9-7199-45E1-841C-BE0313D8052F}

  if (IsATOKActiveInternal()) {
    return TextInputProcessorID::ATOKUnknown;
  }

  // {E6D66705-1EDA-4373-8D01-1D0CB2D054C7}
  static constexpr GUID kJapanist10GUID = {
      0xE6D66705,
      0x1EDA,
      0x4373,
      {0x8D, 0x01, 0x1D, 0x0C, 0xB2, 0xD0, 0x54, 0xC7}};
  if (mActiveTIPGUID == kJapanist10GUID) {
    return TextInputProcessorID::Japanist10;
  }

  return TextInputProcessorID::Unknown;
}

TextInputProcessorID TSFStaticSink::ComputeActiveTIPAsTraditionalChinese() {
  // {B2F9C502-1742-11D4-9790-0080C882687E} (Win8.1, Win10)
  static constexpr GUID kMicrosoftBopomofoGUID = {
      0xB2F9C502,
      0x1742,
      0x11D4,
      {0x97, 0x90, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftBopomofoGUID) {
    return TextInputProcessorID::MicrosoftBopomofo;
  }
  // {4BDF9F03-C7D3-11D4-B2AB-0080C882687E} (Win7, Win8.1, Win10)
  static const GUID kMicrosoftChangJieGUID = {
      0x4BDF9F03,
      0xC7D3,
      0x11D4,
      {0xB2, 0xAB, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftChangJieGUID) {
    return TextInputProcessorID::MicrosoftChangJie;
  }
  // {761309DE-317A-11D4-9B5D-0080C882687E} (Win7)
  static constexpr GUID kMicrosoftPhoneticGUID = {
      0x761309DE,
      0x317A,
      0x11D4,
      {0x9B, 0x5D, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftPhoneticGUID) {
    return TextInputProcessorID::MicrosoftPhonetic;
  }
  // {6024B45F-5C54-11D4-B921-0080C882687E} (Win7, Win8.1, Win10)
  static constexpr GUID kMicrosoftQuickGUID = {
      0x6024B45F,
      0x5C54,
      0x11D4,
      {0xB9, 0x21, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftQuickGUID) {
    return TextInputProcessorID::MicrosoftQuick;
  }
  // {F3BA907A-6C7E-11D4-97FA-0080C882687E} (Win7)
  static constexpr GUID kMicrosoftNewChangJieGUID = {
      0xF3BA907A,
      0x6C7E,
      0x11D4,
      {0x97, 0xFA, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftNewChangJieGUID) {
    return TextInputProcessorID::MicrosoftNewChangJie;
  }
  // {B2F9C502-1742-11D4-9790-0080C882687E} (Win7)
  static constexpr GUID kMicrosoftNewPhoneticGUID = {
      0xB2F9C502,
      0x1742,
      0x11D4,
      {0x97, 0x90, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftNewPhoneticGUID) {
    return TextInputProcessorID::MicrosoftNewPhonetic;
  }
  // {0B883BA0-C1C7-11D4-87F9-0080C882687E} (Win7)
  static constexpr GUID kMicrosoftNewQuickGUID = {
      0x0B883BA0,
      0xC1C7,
      0x11D4,
      {0x87, 0xF9, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftNewQuickGUID) {
    return TextInputProcessorID::MicrosoftNewQuick;
  }

  // NOTE: There are some other Traditional Chinese TIPs installed in Windows:
  // * Chinese Traditional Array (version 6.0)
  //   - {D38EFF65-AA46-4FD5-91A7-67845FB02F5B} (Win7, Win8.1)
  // * Chinese Traditional DaYi (version 6.0)
  //   - {037B2C25-480C-4D7F-B027-D6CA6B69788A} (Win7, Win8.1)

  // {B58630B5-0ED3-4335-BBC9-E77BBCB43CAD}
  static const GUID kFreeChangJieGUID = {
      0xB58630B5,
      0x0ED3,
      0x4335,
      {0xBB, 0xC9, 0xE7, 0x7B, 0xBC, 0xB4, 0x3C, 0xAD}};
  if (mActiveTIPGUID == kFreeChangJieGUID) {
    return TextInputProcessorID::FreeChangJie;
  }

  return TextInputProcessorID::Unknown;
}

TextInputProcessorID TSFStaticSink::ComputeActiveTIPAsSimplifiedChinese() {
  // FYI: This matches with neither "Microsoft Pinyin ABC Input Style" nor
  //      "Microsoft Pinyin New Experience Input Style" on Win7.
  // {FA550B04-5AD7-411F-A5AC-CA038EC515D7} (Win8.1, Win10)
  static constexpr GUID kMicrosoftPinyinGUID = {
      0xFA550B04,
      0x5AD7,
      0x411F,
      {0xA5, 0xAC, 0xCA, 0x03, 0x8E, 0xC5, 0x15, 0xD7}};
  if (mActiveTIPGUID == kMicrosoftPinyinGUID) {
    return TextInputProcessorID::MicrosoftPinyin;
  }

  // {F3BA9077-6C7E-11D4-97FA-0080C882687E} (Win7)
  static constexpr GUID kMicrosoftPinyinNewExperienceInputStyleGUID = {
      0xF3BA9077,
      0x6C7E,
      0x11D4,
      {0x97, 0xFA, 0x00, 0x80, 0xC8, 0x82, 0x68, 0x7E}};
  if (mActiveTIPGUID == kMicrosoftPinyinNewExperienceInputStyleGUID) {
    return TextInputProcessorID::MicrosoftPinyinNewExperienceInputStyle;
  }
  // {82590C13-F4DD-44F4-BA1D-8667246FDF8E} (Win8.1, Win10)
  static constexpr GUID kMicrosoftWubiGUID = {
      0x82590C13,
      0xF4DD,
      0x44F4,
      {0xBA, 0x1D, 0x86, 0x67, 0x24, 0x6F, 0xDF, 0x8E}};
  if (mActiveTIPGUID == kMicrosoftWubiGUID) {
    return TextInputProcessorID::MicrosoftWubi;
  }
  // {E7EA138F-69F8-11D7-A6EA-00065B844311}
  static constexpr GUID kSogouGUID = {
      0xe7ea138f,
      0x69f8,
      0x11d7,
      {0xa6, 0xea, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x11}};
  if (mActiveTIPGUID == kSogouGUID) {
    return TextInputProcessorID::Sogou;
  }
  // {607FDF85-FCC8-4DBD-A365-41296F980C9C}
  static constexpr GUID kWeChatGUID = {
      0x607fdf85,
      0xfcc8,
      0x4dbd,
      {0xa3, 0x65, 0x41, 0x29, 0x6f, 0x98, 0x0c, 0x9c}};
  if (mActiveTIPGUID == kWeChatGUID) {
    return TextInputProcessorID::WeChat;
  }
  // NOTE: There are some other Simplified Chinese TIPs installed in Windows:
  // * Chinese Simplified QuanPin (version 6.0)
  //   - {54FC610E-6ABD-4685-9DDD-A130BDF1B170} (Win8.1)
  // * Chinese Simplified ZhengMa (version 6.0)
  //   - {733B4D81-3BC3-4132-B91A-E9CDD5E2BFC9} (Win8.1)
  // * Chinese Simplified ShuangPin (version 6.0)
  //   - {EF63706D-31C4-490E-9DBB-BD150ADC454B} (Win8.1)
  // * Microsoft Pinyin ABC Input Style
  //   - {FCA121D2-8C6D-41FB-B2DE-A2AD110D4820} (Win7)
  return TextInputProcessorID::Unknown;
}

TextInputProcessorID TSFStaticSink::ComputeActiveTIPAsKorean() {
  // {B5FE1F02-D5F2-4445-9C03-C568F23C99A1} (Win7, Win8.1, Win10)
  static constexpr GUID kMicrosoftIMEForKoreanGUID = {
      0xB5FE1F02,
      0xD5F2,
      0x4445,
      {0x9C, 0x03, 0xC5, 0x68, 0xF2, 0x3C, 0x99, 0xA1}};
  if (mActiveTIPGUID == kMicrosoftIMEForKoreanGUID) {
    return TextInputProcessorID::MicrosoftIMEForKorean;
  }
  // {B60AF051-257A-46BC-B9D3-84DAD819BAFB} (Win8.1, Win10)
  static constexpr GUID kMicrosoftOldHangulGUID = {
      0xB60AF051,
      0x257A,
      0x46BC,
      {0xB9, 0xD3, 0x84, 0xDA, 0xD8, 0x19, 0xBA, 0xFB}};
  if (mActiveTIPGUID == kMicrosoftOldHangulGUID) {
    return TextInputProcessorID::MicrosoftOldHangul;
  }

  // NOTE: There is the other Korean TIP installed in Windows:
  // * Microsoft IME 2010
  //   - {48878C45-93F9-4aaf-A6A1-272CD863C4F5} (Win7)

  return TextInputProcessorID::Unknown;
}

bool TSFStaticSink::Init(ITfThreadMgr* aThreadMgr,
                         ITfInputProcessorProfiles* aInputProcessorProfiles) {
  MOZ_ASSERT(!mThreadMgr && !mInputProcessorProfiles,
             "TSFStaticSink::Init() must be called only once");

  mThreadMgr = aThreadMgr;
  mInputProcessorProfiles = aInputProcessorProfiles;

  RefPtr<ITfSource> source;
  HRESULT hr =
      mThreadMgr->QueryInterface(IID_ITfSource, getter_AddRefs(source));
  if (FAILED(hr)) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p TSFStaticSink::Init() FAILED to get ITfSource "
             "instance (0x%08lX)",
             this, hr));
    return false;
  }

  // NOTE: On Vista or later, Windows let us know activate IME changed only
  //       with ITfInputProcessorProfileActivationSink.
  hr = source->AdviseSink(
      IID_ITfInputProcessorProfileActivationSink,
      static_cast<ITfInputProcessorProfileActivationSink*>(this),
      &mIPProfileCookie);
  if (FAILED(hr) || mIPProfileCookie == TF_INVALID_COOKIE) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p TSFStaticSink::Init() FAILED to install "
             "ITfInputProcessorProfileActivationSink (0x%08lX)",
             this, hr));
    return false;
  }

  MOZ_LOG(gIMELog, LogLevel::Info,
          ("0x%p TSFStaticSink::Init(), "
           "mIPProfileCookie=0x%08lX",
           this, mIPProfileCookie));
  return true;
}

void TSFStaticSink::Destroy() {
  MOZ_LOG(gIMELog, LogLevel::Info,
          ("0x%p TSFStaticSink::Shutdown() "
           "mIPProfileCookie=0x%08lX",
           this, mIPProfileCookie));

  if (mIPProfileCookie != TF_INVALID_COOKIE) {
    RefPtr<ITfSource> source;
    HRESULT hr =
        mThreadMgr->QueryInterface(IID_ITfSource, getter_AddRefs(source));
    if (FAILED(hr)) {
      MOZ_LOG(gIMELog, LogLevel::Error,
              ("0x%p   TSFStaticSink::Shutdown() FAILED to get "
               "ITfSource instance (0x%08lX)",
               this, hr));
    } else {
      hr = source->UnadviseSink(mIPProfileCookie);
      if (FAILED(hr)) {
        MOZ_LOG(gIMELog, LogLevel::Error,
                ("0x%p   TSFTextStore::Shutdown() FAILED to uninstall "
                 "ITfInputProcessorProfileActivationSink (0x%08lX)",
                 this, hr));
      }
    }
  }

  mThreadMgr = nullptr;
  mInputProcessorProfiles = nullptr;
}

STDMETHODIMP TSFStaticSink::OnActivated(DWORD dwProfileType, LANGID langid,
                                        REFCLSID rclsid, REFGUID catid,
                                        REFGUID guidProfile, HKL hkl,
                                        DWORD dwFlags) {
  if ((dwFlags & TF_IPSINK_FLAG_ACTIVE) &&
      (dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT ||
       catid == GUID_TFCAT_TIP_KEYBOARD)) {
    mOnActivatedCalled = true;
    mActiveTIP = TextInputProcessorID::NotComputed;
    mActiveTIPGUID = guidProfile;
    mActiveTIPCLSID = rclsid;
    mLangID = langid & 0xFFFF;
    mIsIMM_IME = IsIMM_IME(hkl);
    GetTIPDescription(rclsid, langid, guidProfile,
                      mActiveTIPKeyboardDescription);
    if (mActiveTIPGUID != GUID_NULL) {
      // key should be "LocaleID|Description".  Although GUID of the
      // profile is unique key since description may be localized for system
      // language, unfortunately, it's too long to record as key with its
      // description.  Therefore, we should record only the description with
      // LocaleID because Microsoft IME may not include language information.
      // 72 is kMaximumKeyStringLength in TelemetryScalar.cpp
      nsAutoString key;
      TSFStaticSink::GetActiveTIPNameForTelemetry(key);
      glean::widget::ime_name_on_windows.Get(NS_ConvertUTF16toUTF8(key))
          .Set(true);
    }
    // Notify IMEHandler of changing active keyboard layout.
    IMEHandler::OnKeyboardLayoutChanged();
  }
  MOZ_LOG(
      gIMELog, LogLevel::Info,
      ("0x%p TSFStaticSink::OnActivated(dwProfileType=%s (0x%08lX), "
       "langid=0x%08X, rclsid=%s, catid=%s, guidProfile=%s, hkl=0x%p, "
       "dwFlags=0x%08lX (TF_IPSINK_FLAG_ACTIVE: %s)), mIsIMM_IME=%s, "
       "mActiveTIPDescription=\"%s\"",
       this,
       dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR
           ? "TF_PROFILETYPE_INPUTPROCESSOR"
       : dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT
           ? "TF_PROFILETYPE_KEYBOARDLAYOUT"
           : "Unknown",
       dwProfileType, langid, AutoClsidCString(rclsid).get(),
       AutoRawGuidCString(catid).get(), AutoRawGuidCString(guidProfile).get(),
       hkl, dwFlags, TSFUtils::BoolToChar(dwFlags & TF_IPSINK_FLAG_ACTIVE),
       TSFUtils::BoolToChar(mIsIMM_IME),
       NS_ConvertUTF16toUTF8(mActiveTIPKeyboardDescription).get()));
  return S_OK;
}

bool TSFStaticSink::EnsureInitActiveTIPKeyboard() {
  if (mOnActivatedCalled) {
    return true;
  }

  RefPtr<ITfInputProcessorProfileMgr> profileMgr;
  HRESULT hr = mInputProcessorProfiles->QueryInterface(
      IID_ITfInputProcessorProfileMgr, getter_AddRefs(profileMgr));
  if (FAILED(hr) || !profileMgr) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p   TSFStaticSink::EnsureInitActiveLanguageProfile(), FAILED "
             "to get input processor profile manager, hr=0x%08lX",
             this, hr));
    return false;
  }

  TF_INPUTPROCESSORPROFILE profile;
  hr = profileMgr->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD, &profile);
  if (hr == S_FALSE) {
    MOZ_LOG(gIMELog, LogLevel::Info,
            ("0x%p   TSFStaticSink::EnsureInitActiveLanguageProfile(), FAILED "
             "to get active keyboard layout profile due to no active profile, "
             "hr=0x%08lX",
             this, hr));
    // XXX Should we call OnActivated() with arguments like non-TIP in this
    //     case?
    return false;
  }
  if (FAILED(hr)) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p   TSFStaticSink::EnsureInitActiveLanguageProfile(), FAILED "
             "to get active TIP keyboard, hr=0x%08lX",
             this, hr));
    return false;
  }

  MOZ_LOG(gIMELog, LogLevel::Info,
          ("0x%p   TSFStaticSink::EnsureInitActiveLanguageProfile(), "
           "calling OnActivated() manually...",
           this));
  OnActivated(profile.dwProfileType, profile.langid, profile.clsid,
              profile.catid, profile.guidProfile, ::GetKeyboardLayout(0),
              TF_IPSINK_FLAG_ACTIVE);
  return true;
}

void TSFStaticSink::GetTIPDescription(REFCLSID aTextService, LANGID aLangID,
                                      REFGUID aProfile,
                                      nsAString& aDescription) {
  aDescription.Truncate();

  if (aTextService == CLSID_NULL || aProfile == GUID_NULL) {
    return;
  }

  BSTR description = nullptr;
  HRESULT hr = mInputProcessorProfiles->GetLanguageProfileDescription(
      aTextService, aLangID, aProfile, &description);
  if (FAILED(hr)) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p   TSFStaticSink::InitActiveTIPDescription() FAILED "
             "due to GetLanguageProfileDescription() failure, hr=0x%08lX",
             this, hr));
    return;
  }

  if (description && description[0]) {
    aDescription.Assign(description);
  }
  ::SysFreeString(description);
}

bool TSFStaticSink::IsTIPCategoryKeyboard(REFCLSID aTextService, LANGID aLangID,
                                          REFGUID aProfile) {
  if (aTextService == CLSID_NULL || aProfile == GUID_NULL) {
    return false;
  }

  RefPtr<IEnumTfLanguageProfiles> enumLangProfiles;
  HRESULT hr = mInputProcessorProfiles->EnumLanguageProfiles(
      aLangID, getter_AddRefs(enumLangProfiles));
  if (FAILED(hr) || !enumLangProfiles) {
    MOZ_LOG(gIMELog, LogLevel::Error,
            ("0x%p   TSFStaticSink::IsTIPCategoryKeyboard(), FAILED "
             "to get language profiles enumerator, hr=0x%08lX",
             this, hr));
    return false;
  }

  TF_LANGUAGEPROFILE profile;
  ULONG fetch = 0;
  while (SUCCEEDED(enumLangProfiles->Next(1, &profile, &fetch)) && fetch) {
    // XXX We're not sure a profile is registered with two or more categories.
    if (profile.clsid == aTextService && profile.guidProfile == aProfile &&
        profile.catid == GUID_TFCAT_TIP_KEYBOARD) {
      return true;
    }
  }
  return false;
}

}  // namespace mozilla::widget

Messung V0.5 in Prozent
C=88 H=99 G=93

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.