diff --git a/scintilla/doc/ScintillaHistory.html b/scintilla/doc/ScintillaHistory.html
index ff81657b1..b25f65b63 100644
--- a/scintilla/doc/ScintillaHistory.html
+++ b/scintilla/doc/ScintillaHistory.html
@@ -556,6 +556,27 @@
Icons Copyright(C) 1998 by Dean S. Jones
+
+
+ -
+ Released 5 July 2019.
+
+ -
+ SciTE enables use of SCI_ commands in user.context.menu.
+
+ -
+ On Win32, stop the IME candidate window moving unnecessarily and position it better.
+ Stop candidate window overlapping composition text and taskbar.
+ Position candidate window closer to composition text.
+ Stop candidate window moving while typing.
+ Align candidate window to target part of composition text.
+ Stop Google IME on Windows 7 moving while typing.
+ Bug #2120.
+ Feature #1300.
+
+
diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx
index 12fd71731..1deb8ca06 100644
--- a/scintilla/win32/ScintillaWin.cxx
+++ b/scintilla/win32/ScintillaWin.cxx
@@ -1063,11 +1063,17 @@ void ScintillaWin::SetCandidateWindowPos() {
IMContext imc(MainHWND());
if (imc.hIMC) {
const Point pos = PointMainCaret();
- CANDIDATEFORM CandForm;
+ const PRectangle rcClient = GetTextRectangle();
+ CANDIDATEFORM CandForm{};
CandForm.dwIndex = 0;
- CandForm.dwStyle = CFS_CANDIDATEPOS;
+ CandForm.dwStyle = CFS_EXCLUDE;
CandForm.ptCurrentPos.x = static_cast(pos.x);
- CandForm.ptCurrentPos.y = static_cast(pos.y + vs.lineHeight);
+ CandForm.ptCurrentPos.y = static_cast(pos.y + std::max(4, vs.lineHeight/4));
+ // Exclude the area of the whole caret line
+ CandForm.rcArea.top = static_cast(pos.y);
+ CandForm.rcArea.bottom = static_cast(pos.y + vs.lineHeight);
+ CandForm.rcArea.left = static_cast(rcClient.left);
+ CandForm.rcArea.right = static_cast(rcClient.right);
::ImmSetCandidateWindow(imc.hIMC, &CandForm);
}
}
@@ -1217,8 +1223,12 @@ sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) {
return 0;
}
- if (initialCompose)
+ if (initialCompose) {
ClearBeforeTentativeStart();
+ }
+
+ // Set candidate window left aligned to beginning of preedit string.
+ SetCandidateWindowPos();
pdoc->TentativeStart(); // TentativeActive from now on.
std::vector imeIndicator = MapImeIndicators(imc.GetImeAttributes());
@@ -1242,6 +1252,11 @@ sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) {
MoveImeCarets(-CurrentPosition() + imeCaretPosDoc);
+ if (std::find(imeIndicator.begin(), imeIndicator.end(), SC_INDICATOR_TARGET) != imeIndicator.end()) {
+ // set candidate window left aligned to beginning of target string.
+ SetCandidateWindowPos();
+ }
+
if (KoreanIME()) {
view.imeCaretBlockOverride = true;
}
@@ -1249,7 +1264,6 @@ sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) {
AddWString(imc.GetCompositionString(GCS_RESULTSTR), CharacterSource::imeResult);
}
EnsureCaretVisible();
- SetCandidateWindowPos();
ShowCaretAtCurrentPosition();
return 0;
}
@@ -2032,6 +2046,11 @@ void ScintillaWin::NotifyCaretMove() noexcept {
void ScintillaWin::UpdateSystemCaret() {
if (hasFocus) {
+ if (pdoc->TentativeActive()) {
+ // ongoing inline mode IME composition, don't inform IME of system caret position.
+ // fix candidate window for Google Japanese IME moved on typing on Win7.
+ return;
+ }
if (HasCaretSizeChanged()) {
DestroySystemCaret();
CreateSystemCaret();