--- a/widget/gtk/IMContextWrapper.cpp
+++ b/widget/gtk/IMContextWrapper.cpp
@@ -174,16 +174,17 @@ IMContextWrapper::IMContextWrapper(nsWin
, mCompositionStart(UINT32_MAX)
, mProcessingKeyEvent(nullptr)
, mCompositionState(eCompositionState_NotComposing)
, mIsIMFocused(false)
, mIsDeletingSurrounding(false)
, mLayoutChanged(false)
, mSetCursorPositionOnKeyEvent(true)
, mPendingResettingIMContext(false)
+ , mRetrieveSurroundingSignalReceived(false)
{
static bool sFirstInstance = true;
if (sFirstInstance) {
sFirstInstance = false;
sUseSimpleContext =
Preferences::GetBool(
"intl.ime.use_simple_context_on_password_field",
kUseSimpleContextDefault);
@@ -925,38 +926,43 @@ IMContextWrapper::Blur()
mIsIMFocused = false;
}
void
IMContextWrapper::OnSelectionChange(nsWindow* aCaller,
const IMENotification& aIMENotification)
{
mSelection.Assign(aIMENotification);
+ bool retrievedSurroundingSignalReceived =
+ mRetrieveSurroundingSignalReceived;
+ mRetrieveSurroundingSignalReceived = false;
if (MOZ_UNLIKELY(IsDestroyed())) {
return;
}
const IMENotification::SelectionChangeDataBase& selectionChangeData =
aIMENotification.mSelectionChangeData;
MOZ_LOG(gGtkIMLog, LogLevel::Info,
("0x%p OnSelectionChange(aCaller=0x%p, aIMENotification={ "
"mSelectionChangeData={ mOffset=%u, Length()=%u, mReversed=%s, "
"mWritingMode=%s, mCausedByComposition=%s, "
"mCausedBySelectionEvent=%s, mOccurredDuringComposition=%s "
- "} }), mCompositionState=%s, mIsDeletingSurrounding=%s",
+ "} }), mCompositionState=%s, mIsDeletingSurrounding=%s, "
+ "mRetrieveSurroundingSignalReceived=%s",
this, aCaller, selectionChangeData.mOffset,
selectionChangeData.Length(),
ToChar(selectionChangeData.mReversed),
GetWritingModeName(selectionChangeData.GetWritingMode()).get(),
ToChar(selectionChangeData.mCausedByComposition),
ToChar(selectionChangeData.mCausedBySelectionEvent),
ToChar(selectionChangeData.mOccurredDuringComposition),
- GetCompositionStateName(), ToChar(mIsDeletingSurrounding)));
+ GetCompositionStateName(), ToChar(mIsDeletingSurrounding),
+ ToChar(retrievedSurroundingSignalReceived)));
if (aCaller != mLastFocusedWindow) {
MOZ_LOG(gGtkIMLog, LogLevel::Error,
("0x%p OnSelectionChange(), FAILED, "
"the caller isn't focused window, mLastFocusedWindow=0x%p",
this, mLastFocusedWindow));
return;
}
@@ -1006,17 +1012,28 @@ IMContextWrapper::OnSelectionChange(nsWi
}
// When the selection change is caused by dispatching composition event,
// selection set event and/or occurred before starting current composition,
// we shouldn't notify IME of that and commit existing composition.
if (!selectionChangeData.mCausedByComposition &&
!selectionChangeData.mCausedBySelectionEvent &&
!occurredBeforeComposition) {
- ResetIME();
+ // Hack for ibus-pinyin. ibus-pinyin will synthesize a set of
+ // composition which commits with empty string after calling
+ // gtk_im_context_reset(). Therefore, selecting text causes
+ // unexpectedly removing it. For preventing it but not breaking the
+ // other IMEs which use surrounding text, we should call it only when
+ // surrounding text has been retrieved after last selection range was
+ // set. If it's not retrieved, that means that current IME doesn't
+ // have any content cache, so, it must not need the notification of
+ // selection change.
+ if (IsComposing() || retrievedSurroundingSignalReceived) {
+ ResetIME();
+ }
}
}
/* static */
void
IMContextWrapper::OnStartCompositionCallback(GtkIMContext* aContext,
IMContextWrapper* aModule)
{
@@ -1159,16 +1176,17 @@ IMContextWrapper::OnRetrieveSurroundingN
return FALSE;
}
NS_ConvertUTF16toUTF8 utf8Str(nsDependentSubstring(uniStr, 0, cursorPos));
uint32_t cursorPosInUTF8 = utf8Str.Length();
AppendUTF16toUTF8(nsDependentSubstring(uniStr, cursorPos), utf8Str);
gtk_im_context_set_surrounding(aContext, utf8Str.get(), utf8Str.Length(),
cursorPosInUTF8);
+ mRetrieveSurroundingSignalReceived = true;
return TRUE;
}
/* static */
gboolean
IMContextWrapper::OnDeleteSurroundingCallback(GtkIMContext* aContext,
gint aOffset,
gint aNChars,