Skip to content

Commit

Permalink
fix(composition): improve compositions and edit sessions (rime#146)
Browse files Browse the repository at this point in the history
* fix(composition): update compositions in edit session

* fix(composition): insert commit text by set range text
  • Loading branch information
nameoverflow authored and lotem committed Mar 22, 2018
1 parent 16c163a commit fbdb667
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 86 deletions.
125 changes: 76 additions & 49 deletions WeaselTSF/Composition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec)

void WeaselTSF::_StartComposition(ITfContext *pContext, BOOL fCUASWorkaroundEnabled)
{
if (!_fCUASWorkaroundTested)
{
/* Test if we need to apply the workaround */
_UpdateCompositionWindow(_pEditSessionContext);
}
else if (!fCUASWorkaroundEnabled)
{
/* Workaround not applied, update candidate window position at this point. */
_UpdateCompositionWindow(_pEditSessionContext);
}
CStartCompositionEditSession *pStartCompositionEditSession;
if ((pStartCompositionEditSession = new CStartCompositionEditSession(this, pContext, fCUASWorkaroundEnabled)) != NULL)
{
Expand All @@ -82,8 +92,8 @@ void WeaselTSF::_StartComposition(ITfContext *pContext, BOOL fCUASWorkaroundEnab
class CEndCompositionEditSession: public CEditSession
{
public:
CEndCompositionEditSession(WeaselTSF *pTextService, ITfContext *pContext, ITfComposition *pComposition)
: CEditSession(pTextService, pContext)
CEndCompositionEditSession(WeaselTSF *pTextService, ITfContext *pContext, ITfComposition *pComposition, bool clear = true)
: CEditSession(pTextService, pContext), _clear(clear)
{
_pComposition = pComposition;
}
Expand All @@ -93,26 +103,27 @@ class CEndCompositionEditSession: public CEditSession

private:
ITfComposition *_pComposition;
bool _clear;
};

STDAPI CEndCompositionEditSession::DoEditSession(TfEditCookie ec)
{
/* Clear the dummy text we set before, if any. */
ITfRange *pCompositionRange;
if (_pComposition->GetRange(&pCompositionRange) == S_OK)
if (_clear && _pComposition->GetRange(&pCompositionRange) == S_OK)
pCompositionRange->SetText(ec, 0, L"", 0);

_pComposition->EndComposition(ec);
_pTextService->OnCompositionTerminated(ec, _pComposition);
return S_OK;
}

void WeaselTSF::_EndComposition(ITfContext *pContext)
void WeaselTSF::_EndComposition(ITfContext *pContext, BOOL clear)
{
CEndCompositionEditSession *pEditSession;
HRESULT hr;

if ((pEditSession = new CEndCompositionEditSession(this, pContext, _pComposition)) != NULL)
if ((pEditSession = new CEndCompositionEditSession(this, pContext, _pComposition, clear)) != NULL)
{
pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);
pEditSession->Release();
Expand Down Expand Up @@ -265,57 +276,73 @@ BOOL WeaselTSF::_ShowInlinePreedit(ITfContext *pContext, const std::shared_ptr<w
}

/* Update Composition */
void WeaselTSF::_UpdateComposition(ITfContext *pContext)
class CInsertTextEditSession : public CEditSession
{
public:
CInsertTextEditSession(WeaselTSF *pTextService, ITfContext *pContext, ITfComposition *pComposition, const std::wstring &text)
: CEditSession(pTextService, pContext), _text(text), _pComposition(pComposition)
{
}

/* ITfEditSession */
STDMETHODIMP DoEditSession(TfEditCookie ec);

private:
std::wstring _text;
ITfComposition *_pComposition;
};

STDMETHODIMP CInsertTextEditSession::DoEditSession(TfEditCookie ec)
{
// get commit string from server
std::wstring commit;
weasel::Status status;
weasel::Config config;
ITfRange *pRange;
TF_SELECTION tfSelection;
HRESULT hRet = S_OK;

if ((hRet = _pComposition->GetRange(&pRange)) != S_OK)
goto Exit;

auto context = std::make_shared<weasel::Context>();
if ((hRet = pRange->SetText(ec, 0, _text.c_str(), _text.length())) != S_OK)
goto Exit;

weasel::ResponseParser parser(&commit, context.get(), &status, &config);
/* update the selection to an insertion point just past the inserted text. */
pRange->Collapse(ec, TF_ANCHOR_END);

bool ok = m_client.GetResponseData(std::ref(parser));
tfSelection.range = pRange;
tfSelection.style.ase = TF_AE_NONE;
tfSelection.style.fInterimChar = FALSE;

if (ok)
_pContext->SetSelection(ec, 1, &tfSelection);

Exit:
if (pRange != NULL)
pRange->Release();

return hRet;

}

BOOL WeaselTSF::_InsertText(ITfContext *pContext, const std::wstring& text)
{
CInsertTextEditSession *pEditSession;
HRESULT hr;

if ((pEditSession = new CInsertTextEditSession(this, pContext, _pComposition, text)) != NULL)
{
if (!commit.empty())
{
// 修复顶字上屏的吞字问题:
// 顶字上屏(如五笔 4 码上屏时),当候选词数 > 1 时,
// 第 5 码输入时会将首选项顶屏。
// 此时由于第五码的输入,composition 应是开启的,同时也要在输入处插入顶字。
// 这里先关闭上一个字的 composition,然后为后续输入开启一个新 composition。
// 有点 dirty 但是 it works ...
if (_IsComposing()) {
_EndComposition(pContext);
}
_InsertText(pContext, commit);
}
if (status.composing && !_IsComposing())
{
if (!_fCUASWorkaroundTested)
{
/* Test if we need to apply the workaround */
_UpdateCompositionWindow(pContext);
}
else if (!_fCUASWorkaroundEnabled || config.inline_preedit)
{
/* Workaround not applied, update candidate window position at this point. */
_UpdateCompositionWindow(pContext);
}
_StartComposition(pContext, _fCUASWorkaroundEnabled && !config.inline_preedit);
}
else if (!status.composing && _IsComposing())
{
_EndComposition(pContext);
}
if (_IsComposing() && config.inline_preedit)
{
_ShowInlinePreedit(pContext, context);
}
pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);
pEditSession->Release();
}

return TRUE;
}

void WeaselTSF::_UpdateComposition(ITfContext *pContext)
{
HRESULT hr;

_pEditSessionContext = pContext;

_pEditSessionContext->RequestEditSession(_tfClientId, this, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);

}

/* Composition State */
Expand Down
69 changes: 34 additions & 35 deletions WeaselTSF/EditSession.cpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,45 @@
#include "stdafx.h"
#include "WeaselTSF.h"
#include "ResponseParser.h"

STDAPI WeaselTSF::DoEditSession(TfEditCookie ec)
{
ITfInsertAtSelection *pInsertAtSelection;
ITfRange *pRange;
TF_SELECTION tfSelection;
// get commit string from server
std::wstring commit;
weasel::Status status;
weasel::Config config;

if (_pEditSessionContext->QueryInterface(IID_ITfInsertAtSelection, (LPVOID *) &pInsertAtSelection) != S_OK)
return E_FAIL;
auto context = std::make_shared<weasel::Context>();

/* insert the text */
if (pInsertAtSelection->InsertTextAtSelection(ec, 0, _editSessionText.c_str(), _editSessionText.length(), &pRange) != S_OK)
{
pInsertAtSelection->Release();
return E_FAIL;
}

/* update the selection to an insertion point just past the inserted text. */
pRange->Collapse(ec, TF_ANCHOR_END);

tfSelection.range = pRange;
tfSelection.style.ase = TF_AE_NONE;
tfSelection.style.fInterimChar = FALSE;
weasel::ResponseParser parser(&commit, context.get(), &status, &config);

_pEditSessionContext->SetSelection(ec, 1, &tfSelection);
bool ok = m_client.GetResponseData(std::ref(parser));

pRange->Release();
pInsertAtSelection->Release();

return S_OK;
if (ok)
{
if (!commit.empty())
{
// For auto-selecting, commit and preedit can both exist.
// Commit and close the original composition first.
if (!_IsComposing()) {
_StartComposition(_pEditSessionContext, _fCUASWorkaroundEnabled && !config.inline_preedit);
}
_InsertText(_pEditSessionContext, commit);
_EndComposition(_pEditSessionContext, false);
}
if (status.composing && !_IsComposing())
{
_StartComposition(_pEditSessionContext, _fCUASWorkaroundEnabled && !config.inline_preedit);
}
else if (!status.composing && _IsComposing())
{
_EndComposition(_pEditSessionContext, true);
}
if (_IsComposing() && config.inline_preedit)
{
_ShowInlinePreedit(_pEditSessionContext, context);
}
}
return TRUE;
}

BOOL WeaselTSF::_InsertText(ITfContext *pContext, const std::wstring& text)
{
HRESULT hr;

_pEditSessionContext = pContext;
_editSessionText = text;

if (_pEditSessionContext->RequestEditSession(_tfClientId, this, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr) != S_OK || hr != S_OK)
return FALSE;

return TRUE;
}
2 changes: 1 addition & 1 deletion WeaselTSF/TextEditSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ STDAPI WeaselTSF::OnEndEdit(ITfContext *pContext, TfEditCookie ecReadOnly, ITfEd
if (_pComposition->GetRange(&pRangeComposition) == S_OK)
{
if (!IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition))
_EndComposition(pContext);
_EndComposition(pContext, true);
pRangeComposition->Release();
}
}
Expand Down
2 changes: 1 addition & 1 deletion WeaselTSF/WeaselTSF.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class WeaselTSF:

/* Composition */
void _StartComposition(ITfContext *pContext, BOOL fCUASWorkaroundEnabled);
void _EndComposition(ITfContext *pContext);
void _EndComposition(ITfContext *pContext, BOOL clear);
BOOL _ShowInlinePreedit(ITfContext *pContext, const std::shared_ptr<weasel::Context> context);
void _UpdateComposition(ITfContext *pContext);
BOOL _IsComposing();
Expand Down

0 comments on commit fbdb667

Please sign in to comment.