Bug 1130937 part.2 nsGtkIMModule should set candidiate window position to bottom left of the target clause in vertical writing mode r=m_kato

This commit is contained in:
Masayuki Nakano 2015-06-11 19:50:15 +09:00
parent 8d0ec572a9
commit 518ed96e43
4 changed files with 82 additions and 28 deletions

View File

@ -410,6 +410,15 @@ public:
return mRanges ? mRanges->TargetClauseOffset() : 0;
}
uint32_t TargetClauseLength() const
{
uint32_t length = UINT32_MAX;
if (mRanges) {
length = mRanges->TargetClauseLength();
}
return length == UINT32_MAX ? mData.Length() : length;
}
uint32_t RangeCount() const
{
return mRanges ? mRanges->Length() : 0;

View File

@ -195,6 +195,18 @@ class TextRangeArray final : public nsAutoTArray<TextRange, 10>
NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
const TextRange* GetTargetClause() const
{
for (uint32_t i = 0; i < Length(); ++i) {
const TextRange& range = ElementAt(i);
if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT ||
range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) {
return &range;
}
}
return nullptr;
}
public:
bool IsComposing() const
{
@ -206,18 +218,20 @@ public:
return false;
}
// Returns target clase offset. If there are selected clauses, this returns
// Returns target clause offset. If there are selected clauses, this returns
// the first selected clause offset. Otherwise, 0.
uint32_t TargetClauseOffset() const
{
for (uint32_t i = 0; i < Length(); ++i) {
const TextRange& range = ElementAt(i);
if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT ||
range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) {
return range.mStartOffset;
}
}
return 0;
const TextRange* range = GetTargetClause();
return range ? range->mStartOffset : 0;
}
// Returns target clause length. If there are selected clauses, this returns
// the first selected clause length. Otherwise, UINT32_MAX.
uint32_t TargetClauseLength() const
{
const TextRange* range = GetTargetClause();
return range ? range->Length() : UINT32_MAX;
}
bool Equals(const TextRangeArray& aOther) const

View File

@ -14,6 +14,7 @@
#include "mozilla/MiscEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextEvents.h"
#include "WritingModes.h"
using namespace mozilla;
using namespace mozilla::widget;
@ -111,7 +112,6 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow)
, mComposingContext(nullptr)
, mCompositionStart(UINT32_MAX)
, mProcessingKeyEvent(nullptr)
, mCompositionTargetOffset(UINT32_MAX)
, mCompositionState(eCompositionState_NotComposing)
, mIsIMFocused(false)
, mIsDeletingSurrounding(false)
@ -535,7 +535,7 @@ nsGtkIMModule::OnUpdateComposition()
return;
}
SetCursorPosition(GetActiveContext(), mCompositionTargetOffset);
SetCursorPosition(GetActiveContext());
}
void
@ -819,7 +819,8 @@ nsGtkIMModule::OnStartCompositionNative(GtkIMContext *aContext)
if (!DispatchCompositionStart(aContext)) {
return;
}
mCompositionTargetOffset = mCompositionStart;
mCompositionTargetRange.mOffset = mCompositionStart;
mCompositionTargetRange.mLength = 0;
}
/* static */
@ -1195,7 +1196,9 @@ nsGtkIMModule::DispatchCompositionChangeEvent(
// We cannot call SetCursorPosition for e10s-aware.
// DispatchEvent is async on e10s, so composition rect isn't updated now
// on tab parent.
mCompositionTargetOffset = targetOffset;
mCompositionTargetRange.mOffset = targetOffset;
mCompositionTargetRange.mLength =
compositionChangeEvent.mRanges->TargetClauseLength();
return true;
}
@ -1238,7 +1241,7 @@ nsGtkIMModule::DispatchCompositionCommitEvent(
NS_COMPOSITION_COMMIT_AS_IS;
mCompositionState = eCompositionState_NotComposing;
mCompositionStart = UINT32_MAX;
mCompositionTargetOffset = UINT32_MAX;
mCompositionTargetRange.Clear();
mDispatchedCompositionString.Truncate();
WidgetCompositionEvent compositionCommitEvent(true, message,
@ -1393,16 +1396,19 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext,
}
void
nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext,
uint32_t aTargetOffset)
nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext)
{
MOZ_LOG(gGtkIMLog, LogLevel::Info,
("GtkIMModule(%p): SetCursorPosition, aContext=%p, aTargetOffset=%u",
this, aContext, aTargetOffset));
("GtkIMModule(%p): SetCursorPosition, aContext=%p, "
"mCompositionTargetRange={ mOffset=%u, mLength=%u }"
"mSelection.mWritingMode=%s",
this, aContext, mCompositionTargetRange.mOffset,
mCompositionTargetRange.mLength,
GetWritingModeName(mSelection.mWritingMode).get()));
if (aTargetOffset == UINT32_MAX) {
if (!mCompositionTargetRange.IsValid()) {
MOZ_LOG(gGtkIMLog, LogLevel::Info,
(" FAILED, aTargetOffset is wrong offset"));
(" FAILED, mCompositionTargetRange is invalid"));
return;
}
@ -1420,7 +1426,15 @@ nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext,
WidgetQueryContentEvent charRect(true, NS_QUERY_TEXT_RECT,
mLastFocusedWindow);
charRect.InitForQueryTextRect(aTargetOffset, 1);
if (mSelection.mWritingMode.IsVertical()) {
// For preventing the candidate window to overlap the target clause,
// we should set fake (typically, very tall) caret rect.
uint32_t length = mCompositionTargetRange.mLength ?
mCompositionTargetRange.mLength : 1;
charRect.InitForQueryTextRect(mCompositionTargetRange.mOffset, length);
} else {
charRect.InitForQueryTextRect(mCompositionTargetRange.mOffset, 1);
}
InitEvent(charRect);
nsEventStatus status;
mLastFocusedWindow->DispatchEvent(&charRect, status);
@ -1429,6 +1443,7 @@ nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext,
(" FAILED, NS_QUERY_TEXT_RECT was failed"));
return;
}
nsWindow* rootWindow =
static_cast<nsWindow*>(mLastFocusedWindow->GetTopLevelWidget());

View File

@ -125,8 +125,27 @@ protected:
// event.
GdkEventKey* mProcessingKeyEvent;
// current target offset of IME composition
uint32_t mCompositionTargetOffset;
struct Range
{
uint32_t mOffset;
uint32_t mLength;
Range()
: mOffset(UINT32_MAX)
, mLength(UINT32_MAX)
{
}
bool IsValid() const { return mOffset != UINT32_MAX; }
void Clear()
{
mOffset = UINT32_MAX;
mLength = UINT32_MAX;
}
};
// current target offset and length of IME composition
Range mCompositionTargetRange;
// mCompositionState indicates current status of composition.
enum eCompositionState {
@ -327,14 +346,11 @@ protected:
const nsAString& aLastDispatchedData);
/**
* Sets the offset's cursor position to IME.
* Move the candidate window with "fake" cursor position.
*
* @param aContext A GtkIMContext which is being handled.
* @param aTargetOffset Offset of a character which is anchor of
* a candidate window. This is offset in
* UTF-16 string.
*/
void SetCursorPosition(GtkIMContext* aContext, uint32_t aTargetOffset);
void SetCursorPosition(GtkIMContext* aContext);
// Queries the current selection offset of the window.
uint32_t GetSelectionOffset(nsWindow* aWindow);