mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 729774 part.1 nsGtkIMModule should manage composition state more closely r=karlt
This commit is contained in:
parent
523a6b04cd
commit
c29ddcb682
@ -114,8 +114,8 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) :
|
||||
#endif
|
||||
mDummyContext(nsnull),
|
||||
mCompositionStart(PR_UINT32_MAX), mProcessingKeyEvent(nsnull),
|
||||
mIsComposing(false), mIsIMFocused(false),
|
||||
mIgnoreNativeCompositionEvent(false)
|
||||
mCompositionState(eCompositionState_NotComposing),
|
||||
mIsIMFocused(false), mIgnoreNativeCompositionEvent(false)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gGtkIMLog) {
|
||||
@ -412,7 +412,7 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent,
|
||||
// composed characters.
|
||||
bool filterThisEvent = isFiltered && mFilterKeyEvent;
|
||||
|
||||
if (mIsComposing && !isFiltered) {
|
||||
if (IsComposing() && !isFiltered) {
|
||||
if (aEvent->type == GDK_KEY_PRESS) {
|
||||
if (!mDispatchedCompositionString.IsEmpty()) {
|
||||
// If there is composition string, we shouldn't dispatch
|
||||
@ -448,8 +448,10 @@ void
|
||||
nsGtkIMModule::OnFocusChangeInGecko(bool aFocus)
|
||||
{
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
("GtkIMModule(%p): OnFocusChangeInGecko, aFocus=%s mIsComposing=%s, mIsIMFocused=%s, mIgnoreNativeCompositionEvent=%s",
|
||||
this, aFocus ? "YES" : "NO", mIsComposing ? "YES" : "NO",
|
||||
("GtkIMModule(%p): OnFocusChangeInGecko, aFocus=%s, "
|
||||
"mCompositionState=%s, mIsIMFocused=%s, "
|
||||
"mIgnoreNativeCompositionEvent=%s",
|
||||
this, aFocus ? "YES" : "NO", GetCompositionStateName(),
|
||||
mIsIMFocused ? "YES" : "NO",
|
||||
mIgnoreNativeCompositionEvent ? "YES" : "NO"));
|
||||
if (aFocus) {
|
||||
@ -463,8 +465,8 @@ void
|
||||
nsGtkIMModule::ResetIME()
|
||||
{
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
("GtkIMModule(%p): ResetIME, mIsComposing=%s, mIsIMFocused=%s",
|
||||
this, mIsComposing ? "YES" : "NO", mIsIMFocused ? "YES" : "NO"));
|
||||
("GtkIMModule(%p): ResetIME, mCompositionState=%s, mIsIMFocused=%s",
|
||||
this, GetCompositionStateName(), mIsIMFocused ? "YES" : "NO"));
|
||||
|
||||
GtkIMContext *im = GetContext();
|
||||
if (NS_UNLIKELY(!im)) {
|
||||
@ -485,8 +487,8 @@ nsGtkIMModule::ResetInputState(nsWindow* aCaller)
|
||||
}
|
||||
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
("GtkIMModule(%p): ResetInputState, aCaller=%p, mIsComposing=%s",
|
||||
this, aCaller, mIsComposing ? "YES" : "NO"));
|
||||
("GtkIMModule(%p): ResetInputState, aCaller=%p, mCompositionState=%s",
|
||||
this, aCaller, GetCompositionStateName()));
|
||||
|
||||
if (aCaller != mLastFocusedWindow) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
@ -495,7 +497,7 @@ nsGtkIMModule::ResetInputState(nsWindow* aCaller)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mIsComposing) {
|
||||
if (!IsComposing()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -524,7 +526,7 @@ nsGtkIMModule::CancelIMEComposition(nsWindow* aCaller)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mIsComposing) {
|
||||
if (!IsComposing()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -830,7 +832,7 @@ nsGtkIMModule::OnEndCompositionNative(GtkIMContext *aContext)
|
||||
// Note that the native commit can be fired *after* ResetIME().
|
||||
mIgnoreNativeCompositionEvent = false;
|
||||
|
||||
if (!mIsComposing || shouldIgnoreThisEvent) {
|
||||
if (!IsComposing() || shouldIgnoreThisEvent) {
|
||||
// If we already handled the commit event, we should do nothing here.
|
||||
return;
|
||||
}
|
||||
@ -868,13 +870,13 @@ nsGtkIMModule::OnChangeCompositionNative(GtkIMContext *aContext)
|
||||
|
||||
nsAutoString compositionString;
|
||||
GetCompositionString(compositionString);
|
||||
if (!mIsComposing && compositionString.IsEmpty()) {
|
||||
if (!IsComposing() && compositionString.IsEmpty()) {
|
||||
mDispatchedCompositionString.Truncate();
|
||||
return; // Don't start the composition with empty string.
|
||||
}
|
||||
|
||||
// Be aware, widget can be gone
|
||||
DispatchTextEvent(compositionString, true);
|
||||
DispatchTextEvent(compositionString, false);
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -989,7 +991,7 @@ nsGtkIMModule::OnCommitCompositionNative(GtkIMContext *aContext,
|
||||
// signal, we would dispatch compositionstart, text, compositionend
|
||||
// events with empty string. Of course, they are unnecessary events
|
||||
// for Web applications and our editor.
|
||||
if (!mIsComposing && !commitString[0]) {
|
||||
if (!IsComposing() && !commitString[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1000,7 +1002,7 @@ nsGtkIMModule::OnCommitCompositionNative(GtkIMContext *aContext,
|
||||
// If IME doesn't change their keyevent that generated this commit,
|
||||
// don't send it through XIM - just send it as a normal key press
|
||||
// event.
|
||||
if (!mIsComposing && mProcessingKeyEvent) {
|
||||
if (!IsComposing() && mProcessingKeyEvent) {
|
||||
char keyval_utf8[8]; /* should have at least 6 bytes of space */
|
||||
gint keyval_utf8_len;
|
||||
guint32 keyval_unicode;
|
||||
@ -1031,7 +1033,7 @@ nsGtkIMModule::CommitCompositionBy(const nsAString& aString)
|
||||
this, NS_ConvertUTF16toUTF8(aString).get(),
|
||||
NS_ConvertUTF16toUTF8(mDispatchedCompositionString).get()));
|
||||
|
||||
if (!DispatchTextEvent(aString, false)) {
|
||||
if (!DispatchTextEvent(aString, true)) {
|
||||
return false;
|
||||
}
|
||||
// We should dispatch the compositionend event here because some IMEs
|
||||
@ -1067,7 +1069,7 @@ nsGtkIMModule::DispatchCompositionStart()
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
("GtkIMModule(%p): DispatchCompositionStart", this));
|
||||
|
||||
if (mIsComposing) {
|
||||
if (IsComposing()) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" WARNING, we're already in composition"));
|
||||
return true;
|
||||
@ -1120,7 +1122,7 @@ nsGtkIMModule::DispatchCompositionStart()
|
||||
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" mCompositionStart=%u", mCompositionStart));
|
||||
mIsComposing = true;
|
||||
mCompositionState = eCompositionState_CompositionStartDispatched;
|
||||
nsCompositionEvent compEvent(true, NS_COMPOSITION_START,
|
||||
mLastFocusedWindow);
|
||||
InitEvent(compEvent);
|
||||
@ -1144,7 +1146,7 @@ nsGtkIMModule::DispatchCompositionEnd()
|
||||
"mDispatchedCompositionString=\"%s\"",
|
||||
this, NS_ConvertUTF16toUTF8(mDispatchedCompositionString).get()));
|
||||
|
||||
if (!mIsComposing) {
|
||||
if (!IsComposing()) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" WARNING, we have alrady finished the composition"));
|
||||
return false;
|
||||
@ -1164,7 +1166,7 @@ nsGtkIMModule::DispatchCompositionEnd()
|
||||
nsEventStatus status;
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip = mLastFocusedWindow;
|
||||
mLastFocusedWindow->DispatchEvent(&compEvent, status);
|
||||
mIsComposing = false;
|
||||
mCompositionState = eCompositionState_NotComposing;
|
||||
mCompositionStart = PR_UINT32_MAX;
|
||||
mDispatchedCompositionString.Truncate();
|
||||
if (static_cast<nsWindow*>(kungFuDeathGrip.get())->IsDestroyed() ||
|
||||
@ -1179,11 +1181,11 @@ nsGtkIMModule::DispatchCompositionEnd()
|
||||
|
||||
bool
|
||||
nsGtkIMModule::DispatchTextEvent(const nsAString &aCompositionString,
|
||||
bool aCheckAttr)
|
||||
bool aIsCommit)
|
||||
{
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
("GtkIMModule(%p): DispatchTextEvent, aCheckAttr=%s",
|
||||
this, aCheckAttr ? "TRUE" : "FALSE"));
|
||||
("GtkIMModule(%p): DispatchTextEvent, aIsCommit=%s",
|
||||
this, aIsCommit ? "TRUE" : "FALSE"));
|
||||
|
||||
if (!mLastFocusedWindow) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
@ -1191,7 +1193,7 @@ nsGtkIMModule::DispatchTextEvent(const nsAString &aCompositionString,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mIsComposing) {
|
||||
if (!IsComposing()) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" The composition wasn't started, force starting..."));
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip = mLastFocusedWindow;
|
||||
@ -1224,7 +1226,7 @@ nsGtkIMModule::DispatchTextEvent(const nsAString &aCompositionString,
|
||||
PRUint32 targetOffset = mCompositionStart;
|
||||
|
||||
nsAutoTArray<nsTextRange, 4> textRanges;
|
||||
if (aCheckAttr) {
|
||||
if (!aIsCommit) {
|
||||
// NOTE: SetTextRangeList() assumes that mDispatchedCompositionString
|
||||
// has been updated already.
|
||||
SetTextRangeList(textRanges);
|
||||
@ -1242,6 +1244,10 @@ nsGtkIMModule::DispatchTextEvent(const nsAString &aCompositionString,
|
||||
textEvent.rangeArray = textRanges.Elements();
|
||||
textEvent.theText = mDispatchedCompositionString.get();
|
||||
|
||||
mCompositionState = aIsCommit ?
|
||||
eCompositionState_CommitTextEventDispatched :
|
||||
eCompositionState_TextEventDispatched;
|
||||
|
||||
mLastFocusedWindow->DispatchEvent(&textEvent, status);
|
||||
if (lastFocusedWindow->IsDestroyed() ||
|
||||
lastFocusedWindow != mLastFocusedWindow) {
|
||||
|
@ -173,12 +173,39 @@ protected:
|
||||
// event.
|
||||
GdkEventKey* mProcessingKeyEvent;
|
||||
|
||||
// mCompositionState indicates current status of composition.
|
||||
enum eCompositionState {
|
||||
eCompositionState_NotComposing,
|
||||
eCompositionState_CompositionStartDispatched,
|
||||
eCompositionState_TextEventDispatched,
|
||||
eCompositionState_CommitTextEventDispatched
|
||||
};
|
||||
eCompositionState mCompositionState;
|
||||
|
||||
bool IsComposing()
|
||||
{
|
||||
return (mCompositionState != eCompositionState_NotComposing);
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
const char* GetCompositionStateName()
|
||||
{
|
||||
switch (mCompositionState) {
|
||||
case eCompositionState_NotComposing:
|
||||
return "NotComposing";
|
||||
case eCompositionState_CompositionStartDispatched:
|
||||
return "CompositionStartDispatched";
|
||||
case eCompositionState_TextEventDispatched:
|
||||
return "TextEventDispatched";
|
||||
case eCompositionState_CommitTextEventDispatched:
|
||||
return "CommitTextEventDispatched";
|
||||
default:
|
||||
return "InvaildState";
|
||||
}
|
||||
}
|
||||
#endif // PR_LOGGING
|
||||
|
||||
|
||||
// mIsComposing is set to TRUE when we dispatch the composition start
|
||||
// event. And it's set to FALSE when we dispatches the composition end
|
||||
// event. Note that mCompositionString can be empty string even if this is
|
||||
// TRUE.
|
||||
bool mIsComposing;
|
||||
// mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
|
||||
// it's set to FALSE when we call gtk_im_context_focus_out().
|
||||
bool mIsIMFocused;
|
||||
@ -303,10 +330,10 @@ protected:
|
||||
bool DispatchCompositionStart();
|
||||
bool DispatchCompositionEnd();
|
||||
|
||||
// Dispatches a text event. If aCheckAttr is TRUE, dispatches a committed
|
||||
// Dispatches a text event. If aIsCommit is TRUE, dispatches a committed
|
||||
// text event. Otherwise, dispatches a composing text event.
|
||||
bool DispatchTextEvent(const nsAString& aCompositionString,
|
||||
bool aCheckAttr);
|
||||
bool aIsCommit);
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user