Bug 966157 - Part 2. Child process should listen NOTIFY_IME_OF_POSITION_CHANGE. r=masayuki

This commit is contained in:
Makoto Kato 2014-12-15 18:37:00 +09:00
parent 327fa03357
commit 846f5a8420
5 changed files with 164 additions and 29 deletions

View File

@ -234,6 +234,16 @@ parent:
*/
prio(urgent) async NotifyIMEEditorRect(nsIntRect rect);
/**
* Notifies chrome to position change
*
* editorRect Rect of current focused editor
* compositionRects Rects of current composition string
*/
prio(urgent) async NotifyIMEPositionChange(nsIntRect editorRect,
nsIntRect[] compositionRects,
nsIntRect caretRect);
/**
* Instructs chrome to end any pending composition
*

View File

@ -1495,6 +1495,29 @@ TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
return true;
}
bool
TabParent::RecvNotifyIMEPositionChange(
const nsIntRect& aEditorRect,
const InfallibleTArray<nsIntRect>& aCompositionRects,
const nsIntRect& aCaretRect)
{
mIMEEditorRect = aEditorRect;
mIMECompositionRects = aCompositionRects;
mIMECaretRect = aCaretRect;
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
const nsIMEUpdatePreference updatePreference =
widget->GetIMEUpdatePreference();
if (updatePreference.WantPositionChanged()) {
widget->NotifyIME(IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
}
return true;
}
bool
TabParent::RecvRequestFocus(const bool& aCanRaise)
{

View File

@ -179,6 +179,10 @@ public:
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
bool* aConsumedByIME) MOZ_OVERRIDE;
virtual bool RecvNotifyIMEEditorRect(const nsIntRect& aRect) MOZ_OVERRIDE;
virtual bool RecvNotifyIMEPositionChange(
const nsIntRect& aEditoRect,
const InfallibleTArray<nsIntRect>& aCompositionRects,
const nsIntRect& aCaretRect) MOZ_OVERRIDE;
virtual bool RecvEndIMEComposition(const bool& aCancel,
nsString* aComposition) MOZ_OVERRIDE;
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,

View File

@ -448,6 +448,8 @@ PuppetWidget::NotifyIME(const IMENotification& aIMENotification)
return NotifyIMEOfUpdateComposition();
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
return NotifyIMEOfMouseButtonEvent(aIMENotification);
case NOTIFY_IME_OF_POSITION_CHANGE:
return NotifyIMEOfPositionChange();
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -546,57 +548,110 @@ PuppetWidget::NotifyIMEOfUpdateComposition()
NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
nsRefPtr<TextComposition> textComposition =
IMEStateManager::GetTextCompositionFor(this);
NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE);
nsEventStatus status;
nsTArray<nsIntRect> textRectArray(textComposition->String().Length());
uint32_t startOffset = textComposition->NativeOffsetOfStartComposition();
uint32_t endOffset = textComposition->String().Length() + startOffset;
for (uint32_t i = startOffset; i < endOffset; i++) {
WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, this);
InitEvent(textRect, nullptr);
textRect.InitForQueryTextRect(i, 1);
DispatchEvent(&textRect, status);
NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
textRectArray.AppendElement(textRect.mReply.mRect);
uint32_t startOffset;
uint32_t targetCauseOffset;
nsAutoTArray<nsIntRect, 16> textRectArray;
if (!GetCompositionRects(startOffset,
textRectArray,
targetCauseOffset)) {
return NS_ERROR_FAILURE;
}
uint32_t targetCauseOffset = textComposition->OffsetOfTargetClause();
WidgetQueryContentEvent caretRect(true, NS_QUERY_CARET_RECT, this);
InitEvent(caretRect, nullptr);
caretRect.InitForQueryCaretRect(targetCauseOffset);
DispatchEvent(&caretRect, status);
NS_ENSURE_TRUE(caretRect.mSucceeded, NS_ERROR_FAILURE);
nsIntRect caretRect;
GetCaretRect(caretRect, targetCauseOffset);
mTabChild->SendNotifyIMESelectedCompositionRect(startOffset,
textRectArray,
targetCauseOffset,
caretRect.mReply.mRect);
caretRect);
return NS_OK;
}
bool
PuppetWidget::GetCompositionRects(uint32_t& aStartOffset,
nsTArray<nsIntRect>& aTextRectArray,
uint32_t& aTargetCauseOffset)
{
nsRefPtr<TextComposition> textComposition =
IMEStateManager::GetTextCompositionFor(this);
NS_ENSURE_TRUE(textComposition, false);
nsEventStatus status;
aTextRectArray.SetCapacity(textComposition->String().Length());
aStartOffset = textComposition->NativeOffsetOfStartComposition();
aTargetCauseOffset = textComposition->OffsetOfTargetClause();
uint32_t endOffset = textComposition->String().Length() + aStartOffset;
for (uint32_t i = aStartOffset; i < endOffset; i++) {
WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, this);
InitEvent(textRect, nullptr);
textRect.InitForQueryTextRect(i, 1);
DispatchEvent(&textRect, status);
NS_ENSURE_TRUE(textRect.mSucceeded, false);
aTextRectArray.AppendElement(textRect.mReply.mRect);
}
return true;
}
uint32_t
PuppetWidget::GetCaretOffset()
{
nsEventStatus status;
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT, this);
InitEvent(selection, nullptr);
DispatchEvent(&selection, status);
NS_ENSURE_TRUE(selection.mSucceeded, 0);
return selection.mReply.mOffset;
}
bool
PuppetWidget::GetCaretRect(nsIntRect& aCaretRect, uint32_t aCaretOffset)
{
nsEventStatus status;
WidgetQueryContentEvent caretRect(true, NS_QUERY_CARET_RECT, this);
InitEvent(caretRect, nullptr);
caretRect.InitForQueryCaretRect(aCaretOffset);
DispatchEvent(&caretRect, status);
NS_ENSURE_TRUE(caretRect.mSucceeded, false);
aCaretRect = caretRect.mReply.mRect;
return true;
}
nsresult
PuppetWidget::NotifyIMEOfEditorRect()
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}
nsIntRect rect;
if (!GetEditorRect(rect)) {
return NS_ERROR_FAILURE;
}
mTabChild->SendNotifyIMEEditorRect(rect);
return NS_OK;
}
bool
PuppetWidget::GetEditorRect(nsIntRect& aRect)
{
nsEventStatus status;
WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, this);
InitEvent(editorRectEvent);
DispatchEvent(&editorRectEvent, status);
if (editorRectEvent.mSucceeded) {
mTabChild->SendNotifyIMEEditorRect(editorRectEvent.mReply.mRect);
if (NS_WARN_IF(!editorRectEvent.mSucceeded)) {
return false;
}
aRect = editorRectEvent.mReply.mRect;
return NS_OK;
return true;
}
nsIMEUpdatePreference
PuppetWidget::GetIMEUpdatePreference()
{
@ -604,7 +659,8 @@ PuppetWidget::GetIMEUpdatePreference()
// e10s requires IME information cache into TabParent
return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
#else
// B2G doesn't handle IME as widget-level.
return nsIMEUpdatePreference();
@ -695,6 +751,40 @@ PuppetWidget::NotifyIMEOfMouseButtonEvent(
return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK;
}
nsresult
PuppetWidget::NotifyIMEOfPositionChange()
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}
nsIntRect editorRect;
if (!GetEditorRect(editorRect)) {
return NS_ERROR_FAILURE;
}
uint32_t startOffset;
uint32_t targetCauseOffset;
nsAutoTArray<nsIntRect, 16> textRectArray;
if (!GetCompositionRects(startOffset,
textRectArray,
targetCauseOffset)) {
// no composition string, get caret offset by NS_QUERY_SELECTED_TEXT
targetCauseOffset = GetCaretOffset();
}
nsIntRect caretRect;
GetCaretRect(caretRect, targetCauseOffset);
if (!mTabChild->SendNotifyIMEPositionChange(editorRect, textRectArray,
caretRect)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
PuppetWidget::SetCursor(nsCursor aCursor)
{

View File

@ -217,6 +217,14 @@ private:
nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification);
nsresult NotifyIMEOfEditorRect();
nsresult NotifyIMEOfPositionChange();
bool GetEditorRect(nsIntRect& aEditorRect);
bool GetCompositionRects(uint32_t& aStartOffset,
nsTArray<nsIntRect>& aRectArray,
uint32_t& aTargetCauseOffset);
bool GetCaretRect(nsIntRect& aCaretRect, uint32_t aCaretOffset);
uint32_t GetCaretOffset();
class PaintTask : public nsRunnable {
public: