2025-11-28 00:35:46 +09:00

300 lines
8.4 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) 2003 Microsoft Corporation. All rights reserved.
//
// KeyEventSink.cpp
//
// ITfKeyEventSink implementation.
//
//////////////////////////////////////////////////////////////////////
#include "Globals.h"
#include "TextService.h"
#include "CandidateList.h"
//
// GUID for the preserved keys.
//
/* 6a0bde41-6adf-11d7-a6ea-00065b84435c */
static const GUID GUID_PRESERVEDKEY_ONOFF = {
0x6a0bde41,
0x6adf,
0x11d7,
{0xa6, 0xea, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c}
};
/* 6a0bde42-6adf-11d7-a6ea-00065b84435c */
static const GUID GUID_PRESERVEDKEY_F6 = {
0x6a0bde42,
0x6adf,
0x11d7,
{0xa6, 0xea, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c}
};
//
// the preserved keys declaration
//
// VK_KANJI is the virtual key for Kanji key, which is available in 106
// Japanese keyboard.
//
static const TF_PRESERVEDKEY c_pkeyOnOff0 = { 0xC0, TF_MOD_ALT };
static const TF_PRESERVEDKEY c_pkeyOnOff1 = { VK_KANJI, TF_MOD_IGNORE_ALL_MODIFIER };
static const TF_PRESERVEDKEY c_pkeyF6 = { VK_F6, TF_MOD_ON_KEYUP };
//
// the description for the preserved keys
//
static const WCHAR c_szPKeyOnOff[] = L"OnOff";
static const WCHAR c_szPKeyF6[] = L"Function 6";
//+---------------------------------------------------------------------------
//
// _IsKeyEaten
//
//----------------------------------------------------------------------------
BOOL CTextService::_IsKeyEaten(ITfContext *pContext, WPARAM wParam)
{
// if the keyboard is disabled, we don't eat keys.
if (_IsKeyboardDisabled())
return FALSE;
// if the keyboard is closed, we don't eat keys.
if (!_IsKeyboardOpen())
return FALSE;
//
// The text service key handler does not do anything while the candidate
// window is shown.
// The candidate list handles the keys through ITfContextKeyEventSink.
//
if (_pCandidateList &&
_pCandidateList->_IsContextCandidateWindow(pContext))
{
return FALSE;
}
// eat only keys that CKeyHandlerEditSession can hadles.
switch (wParam)
{
case VK_LEFT:
case VK_RIGHT:
case VK_RETURN:
case VK_SPACE:
if (_IsComposing())
return TRUE;
return FALSE;
}
if (wParam >= 'A' && wParam <= 'Z')
return TRUE;
return FALSE;
}
//+---------------------------------------------------------------------------
//
// OnSetFocus
//
// Called by the system whenever this service gets the keystroke device focus.
//----------------------------------------------------------------------------
STDAPI CTextService::OnSetFocus(BOOL fForeground)
{
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnTestKeyDown
//
// Called by the system to query this service wants a potential keystroke.
//----------------------------------------------------------------------------
STDAPI CTextService::OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
{
*pfEaten = _IsKeyEaten(pContext, wParam);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnKeyDown
//
// Called by the system to offer this service a keystroke. If *pfEaten == TRUE
// on exit, the application will not handle the keystroke.
//----------------------------------------------------------------------------
STDAPI CTextService::OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
{
*pfEaten = _IsKeyEaten(pContext, wParam);
if (*pfEaten)
{
_InvokeKeyHandler(pContext, wParam, lParam);
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnTestKeyUp
//
// Called by the system to query this service wants a potential keystroke.
//----------------------------------------------------------------------------
STDAPI CTextService::OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
{
*pfEaten = _IsKeyEaten(pContext, wParam);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnKeyUp
//
// Called by the system to offer this service a keystroke. If *pfEaten == TRUE
// on exit, the application will not handle the keystroke.
//----------------------------------------------------------------------------
STDAPI CTextService::OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
{
*pfEaten = _IsKeyEaten(pContext, wParam);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnPreservedKey
//
// Called when a hotkey (registered by us, or by the system) is typed.
//----------------------------------------------------------------------------
STDAPI CTextService::OnPreservedKey(ITfContext *pContext, REFGUID rguid, BOOL *pfEaten)
{
if (IsEqualGUID(rguid, GUID_PRESERVEDKEY_ONOFF))
{
BOOL fOpen = _IsKeyboardOpen();
_SetKeyboardOpen(fOpen ? FALSE : TRUE);
*pfEaten = TRUE;
}
else
{
*pfEaten = FALSE;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// _InitKeyEventSink
//
// Advise a keystroke sink.
//----------------------------------------------------------------------------
BOOL CTextService::_InitKeyEventSink()
{
ITfKeystrokeMgr *pKeystrokeMgr;
HRESULT hr;
if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
return FALSE;
hr = pKeystrokeMgr->AdviseKeyEventSink(_tfClientId, (ITfKeyEventSink *)this, TRUE);
pKeystrokeMgr->Release();
return (hr == S_OK);
}
//+---------------------------------------------------------------------------
//
// _UninitKeyEventSink
//
// Unadvise a keystroke sink. Assumes we have advised one already.
//----------------------------------------------------------------------------
void CTextService::_UninitKeyEventSink()
{
ITfKeystrokeMgr *pKeystrokeMgr;
if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
return;
pKeystrokeMgr->UnadviseKeyEventSink(_tfClientId);
pKeystrokeMgr->Release();
}
//+---------------------------------------------------------------------------
//
// _InitPreservedKey
//
// Register a hot key.
//----------------------------------------------------------------------------
BOOL CTextService::_InitPreservedKey()
{
ITfKeystrokeMgr *pKeystrokeMgr;
HRESULT hr;
if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
return FALSE;
// register Alt+~ key
hr = pKeystrokeMgr->PreserveKey(_tfClientId,
GUID_PRESERVEDKEY_ONOFF,
&c_pkeyOnOff0,
c_szPKeyOnOff,
lstrlen(c_szPKeyOnOff));
// register KANJI key
hr = pKeystrokeMgr->PreserveKey(_tfClientId,
GUID_PRESERVEDKEY_ONOFF,
&c_pkeyOnOff1,
c_szPKeyOnOff,
lstrlen(c_szPKeyOnOff));
// register F6 key
hr = pKeystrokeMgr->PreserveKey(_tfClientId,
GUID_PRESERVEDKEY_F6,
&c_pkeyF6,
c_szPKeyF6,
lstrlen(c_szPKeyF6));
pKeystrokeMgr->Release();
return (hr == S_OK);
}
//+---------------------------------------------------------------------------
//
// _UninitPreservedKey
//
// Uninit a hot key.
//----------------------------------------------------------------------------
void CTextService::_UninitPreservedKey()
{
ITfKeystrokeMgr *pKeystrokeMgr;
if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
return;
pKeystrokeMgr->UnpreserveKey(GUID_PRESERVEDKEY_ONOFF, &c_pkeyOnOff0);
pKeystrokeMgr->UnpreserveKey(GUID_PRESERVEDKEY_ONOFF, &c_pkeyOnOff1);
pKeystrokeMgr->UnpreserveKey(GUID_PRESERVEDKEY_F6, &c_pkeyF6);
pKeystrokeMgr->Release();
}