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
Родитель 62347a8f7b
Коммит 6bf9f859e7
5 изменённых файлов: 164 добавлений и 29 удалений

Просмотреть файл

@ -234,6 +234,16 @@ parent:
*/ */
prio(urgent) async NotifyIMEEditorRect(nsIntRect rect); 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 * Instructs chrome to end any pending composition
* *

Просмотреть файл

@ -1460,6 +1460,29 @@ TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
return true; 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 bool
TabParent::RecvRequestFocus(const bool& aCanRaise) TabParent::RecvRequestFocus(const bool& aCanRaise)
{ {

Просмотреть файл

@ -179,6 +179,10 @@ public:
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage, virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
bool* aConsumedByIME) MOZ_OVERRIDE; bool* aConsumedByIME) MOZ_OVERRIDE;
virtual bool RecvNotifyIMEEditorRect(const nsIntRect& aRect) 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, virtual bool RecvEndIMEComposition(const bool& aCancel,
nsString* aComposition) MOZ_OVERRIDE; nsString* aComposition) MOZ_OVERRIDE;
virtual bool RecvGetInputContext(int32_t* aIMEEnabled, virtual bool RecvGetInputContext(int32_t* aIMEEnabled,

Просмотреть файл

@ -448,6 +448,8 @@ PuppetWidget::NotifyIME(const IMENotification& aIMENotification)
return NotifyIMEOfUpdateComposition(); return NotifyIMEOfUpdateComposition();
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT: case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
return NotifyIMEOfMouseButtonEvent(aIMENotification); return NotifyIMEOfMouseButtonEvent(aIMENotification);
case NOTIFY_IME_OF_POSITION_CHANGE:
return NotifyIMEOfPositionChange();
default: default:
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
@ -546,57 +548,110 @@ PuppetWidget::NotifyIMEOfUpdateComposition()
NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
nsRefPtr<TextComposition> textComposition = uint32_t startOffset;
IMEStateManager::GetTextCompositionFor(this); uint32_t targetCauseOffset;
NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE); nsAutoTArray<nsIntRect, 16> textRectArray;
if (!GetCompositionRects(startOffset,
nsEventStatus status; textRectArray,
nsTArray<nsIntRect> textRectArray(textComposition->String().Length()); targetCauseOffset)) {
uint32_t startOffset = textComposition->NativeOffsetOfStartComposition(); return NS_ERROR_FAILURE;
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);
} }
nsIntRect caretRect;
uint32_t targetCauseOffset = textComposition->OffsetOfTargetClause(); GetCaretRect(caretRect, targetCauseOffset);
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);
mTabChild->SendNotifyIMESelectedCompositionRect(startOffset, mTabChild->SendNotifyIMESelectedCompositionRect(startOffset,
textRectArray, textRectArray,
targetCauseOffset, targetCauseOffset,
caretRect.mReply.mRect); caretRect);
return NS_OK; 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 nsresult
PuppetWidget::NotifyIMEOfEditorRect() PuppetWidget::NotifyIMEOfEditorRect()
{ {
#ifndef MOZ_CROSS_PROCESS_IME #ifndef MOZ_CROSS_PROCESS_IME
return NS_OK; return NS_OK;
#endif #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; nsEventStatus status;
WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, this); WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, this);
InitEvent(editorRectEvent); InitEvent(editorRectEvent);
DispatchEvent(&editorRectEvent, status); DispatchEvent(&editorRectEvent, status);
if (editorRectEvent.mSucceeded) { if (NS_WARN_IF(!editorRectEvent.mSucceeded)) {
mTabChild->SendNotifyIMEEditorRect(editorRectEvent.mReply.mRect); return false;
} }
aRect = editorRectEvent.mReply.mRect;
return NS_OK; return true;
} }
nsIMEUpdatePreference nsIMEUpdatePreference
PuppetWidget::GetIMEUpdatePreference() PuppetWidget::GetIMEUpdatePreference()
{ {
@ -604,7 +659,8 @@ PuppetWidget::GetIMEUpdatePreference()
// e10s requires IME information cache into TabParent // e10s requires IME information cache into TabParent
return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates | return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE | nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE); nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
#else #else
// B2G doesn't handle IME as widget-level. // B2G doesn't handle IME as widget-level.
return nsIMEUpdatePreference(); return nsIMEUpdatePreference();
@ -695,6 +751,40 @@ PuppetWidget::NotifyIMEOfMouseButtonEvent(
return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK; 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 NS_IMETHODIMP
PuppetWidget::SetCursor(nsCursor aCursor) PuppetWidget::SetCursor(nsCursor aCursor)
{ {

Просмотреть файл

@ -217,6 +217,14 @@ private:
nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification); nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification); nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification);
nsresult NotifyIMEOfEditorRect(); 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 { class PaintTask : public nsRunnable {
public: public: