Bug 935821 - Part 1. Notify IME Compostion to widget. r=masayuki

This commit is contained in:
Makoto Kato 2013-11-07 09:11:11 +09:00
Родитель 446f6a3744
Коммит 1eaa8a3e12
11 изменённых файлов: 135 добавлений и 1 удалений

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

@ -26,6 +26,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent) : WidgetGUIEvent* aEvent) :
mPresContext(aPresContext), mNode(aNode), mPresContext(aPresContext), mNode(aNode),
mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext), mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
mCompositionStartOffset(0), mCompositionTargetOffset(0),
mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests) mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
{ {
} }
@ -36,6 +37,8 @@ TextComposition::TextComposition(const TextComposition& aOther)
mPresContext = aOther.mPresContext; mPresContext = aOther.mPresContext;
mNode = aOther.mNode; mNode = aOther.mNode;
mLastData = aOther.mLastData; mLastData = aOther.mLastData;
mCompositionStartOffset = aOther.mCompositionStartOffset;
mCompositionTargetOffset = aOther.mCompositionTargetOffset;
mIsSynthesizedForTests = aOther.mIsSynthesizedForTests; mIsSynthesizedForTests = aOther.mIsSynthesizedForTests;
} }
@ -56,6 +59,51 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
nsEventDispatcher::Dispatch(mNode, mPresContext, nsEventDispatcher::Dispatch(mNode, mPresContext,
aEvent, nullptr, aStatus, aCallBack); aEvent, nullptr, aStatus, aCallBack);
// Notify composition update to widget if possible
NotityUpdateComposition(aEvent);
}
void
TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent)
{
nsEventStatus status;
// When compositon start, notify the rect of first offset character.
// When not compositon start, notify the rect of selected composition
// string if text event.
if (aEvent->message == NS_COMPOSITION_START) {
nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget();
// Update composition start offset
WidgetQueryContentEvent selectedTextEvent(true,
NS_QUERY_SELECTED_TEXT,
widget);
widget->DispatchEvent(&selectedTextEvent, status);
if (selectedTextEvent.mSucceeded) {
mCompositionStartOffset = selectedTextEvent.mReply.mOffset;
} else {
// Unknown offset
NS_WARNING("Cannot get start offset of IME composition");
mCompositionStartOffset = 0;
}
mCompositionTargetOffset = mCompositionStartOffset;
} else if (aEvent->eventStructType != NS_TEXT_EVENT) {
return;
} else {
WidgetTextEvent* textEvent = aEvent->AsTextEvent();
mCompositionTargetOffset = mCompositionStartOffset;
for (uint32_t i = 0; i < textEvent->rangeCount; i++) {
TextRange& range = textEvent->rangeArray[i];
if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT ||
range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) {
mCompositionTargetOffset += range.mStartOffset;
break;
}
}
}
NotifyIME(widget::NotificationToIME::NOTIFY_IME_OF_COMPOSITION_UPDATE);
} }
void void

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

@ -12,6 +12,7 @@
#include "nsIWidget.h" #include "nsIWidget.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsPresContext.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h" #include "mozilla/EventForwards.h"
@ -66,6 +67,11 @@ public:
*/ */
nsresult NotifyIME(widget::NotificationToIME aNotification); nsresult NotifyIME(widget::NotificationToIME aNotification);
/**
* the offset of first selected clause or start of of compositon
*/
uint32_t OffsetOfTargetClause() const { return mCompositionTargetOffset; }
private: private:
// This class holds nsPresContext weak. This instance shouldn't block // This class holds nsPresContext weak. This instance shouldn't block
// destroying it. When the presContext is being destroyed, it's notified to // destroying it. When the presContext is being destroyed, it's notified to
@ -82,6 +88,12 @@ private:
// the compositionstart event). // the compositionstart event).
nsString mLastData; nsString mLastData;
// Offset of the composition string from start of the editor
uint32_t mCompositionStartOffset;
// Offset of the selected clause of the composition string from start of the
// editor
uint32_t mCompositionTargetOffset;
// See the comment for IsSynthesizedForTests(). // See the comment for IsSynthesizedForTests().
bool mIsSynthesizedForTests; bool mIsSynthesizedForTests;
@ -96,6 +108,11 @@ private:
nsEventStatus* aStatus, nsEventStatus* aStatus,
nsDispatchingCallback* aCallBack); nsDispatchingCallback* aCallBack);
/**
* Calculate composition offset then notify composition update to widget
*/
void NotityUpdateComposition(WidgetGUIEvent* aEvent);
/** /**
* CompositionEventDispatcher dispatches the specified composition (or text) * CompositionEventDispatcher dispatches the specified composition (or text)
* event. * event.

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

@ -598,6 +598,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
return aWidget->NotifyIME(aNotification); return aWidget->NotifyIME(aNotification);
case REQUEST_TO_COMMIT_COMPOSITION: case REQUEST_TO_COMMIT_COMPOSITION:
case REQUEST_TO_CANCEL_COMPOSITION: case REQUEST_TO_CANCEL_COMPOSITION:
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
return composition ? aWidget->NotifyIME(aNotification) : NS_OK; return composition ? aWidget->NotifyIME(aNotification) : NS_OK;
default: default:
MOZ_CRASH("Unsupported notification"); MOZ_CRASH("Unsupported notification");
@ -1125,3 +1126,9 @@ nsIMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSel,
NS_ADDREF(*aRoot = sTextStateObserver->mRootContent); NS_ADDREF(*aRoot = sTextStateObserver->mRootContent);
return NS_OK; return NS_OK;
} }
TextComposition*
nsIMEStateManager::GetTextComposition(nsIWidget* aWidget)
{
return sTextCompositions->GetCompositionFor(aWidget);
}

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

@ -20,6 +20,7 @@ class nsISelection;
namespace mozilla { namespace mozilla {
class TextCompositionArray; class TextCompositionArray;
class TextComposition;
} // namespace mozilla } // namespace mozilla
/* /*
@ -94,6 +95,11 @@ public:
nsEventStatus* aStatus, nsEventStatus* aStatus,
nsDispatchingCallback* aCallBack); nsDispatchingCallback* aCallBack);
/**
* Get TextComposition from widget.
*/
static mozilla::TextComposition* GetTextComposition(nsIWidget* aWidget);
/** /**
* Send a notification to IME. It depends on the IME or platform spec what * Send a notification to IME. It depends on the IME or platform spec what
* will occur (or not occur). * will occur (or not occur).

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

@ -131,6 +131,14 @@ parent:
*/ */
NotifyIMETextChange(uint32_t offset, uint32_t end, uint32_t newEnd); NotifyIMETextChange(uint32_t offset, uint32_t end, uint32_t newEnd);
/**
* Notifies chrome that there is a IME compostion rect updated
*
* offset The starting offset of this rect
* rect The rect of first character of selected IME composition
*/
NotifyIMESelectedCompositionRect(uint32_t offset, nsIntRect rect);
/** /**
* Notifies chrome that there has been a change in selection * Notifies chrome that there has been a change in selection
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates * Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates

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

@ -992,6 +992,18 @@ TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
return true; return true;
} }
bool
TabParent::RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
const nsIntRect& aRect)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
widget->NotifyIME(NOTIFY_IME_OF_COMPOSITION_UPDATE);
return true;
}
bool bool
TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno, TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
const uint32_t& aAnchor, const uint32_t& aAnchor,

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

@ -144,6 +144,8 @@ public:
virtual bool RecvNotifyIMETextChange(const uint32_t& aStart, virtual bool RecvNotifyIMETextChange(const uint32_t& aStart,
const uint32_t& aEnd, const uint32_t& aEnd,
const uint32_t& aNewEnd); const uint32_t& aNewEnd);
virtual bool RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
const nsIntRect& aRect);
virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno, virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
const uint32_t& aAnchor, const uint32_t& aAnchor,
const uint32_t& aFocus); const uint32_t& aFocus);

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

@ -450,7 +450,9 @@ enum NotificationToIME {
// Selection in the focused editable content is changed // Selection in the focused editable content is changed
NOTIFY_IME_OF_SELECTION_CHANGE, NOTIFY_IME_OF_SELECTION_CHANGE,
REQUEST_TO_COMMIT_COMPOSITION, REQUEST_TO_COMMIT_COMPOSITION,
REQUEST_TO_CANCEL_COMPOSITION REQUEST_TO_CANCEL_COMPOSITION,
// Composition string has been updated
NOTIFY_IME_OF_COMPOSITION_UPDATE
}; };
} // namespace widget } // namespace widget

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

@ -19,6 +19,8 @@
#include "mozilla/TextEvents.h" #include "mozilla/TextEvents.h"
#include "PuppetWidget.h" #include "PuppetWidget.h"
#include "nsIWidgetListener.h" #include "nsIWidgetListener.h"
#include "nsIMEStateManager.h"
#include "TextComposition.h"
using namespace mozilla::dom; using namespace mozilla::dom;
using namespace mozilla::hal; using namespace mozilla::hal;
@ -388,6 +390,8 @@ PuppetWidget::NotifyIME(NotificationToIME aNotification)
return NotifyIMEOfFocusChange(false); return NotifyIMEOfFocusChange(false);
case NOTIFY_IME_OF_SELECTION_CHANGE: case NOTIFY_IME_OF_SELECTION_CHANGE:
return NotifyIMEOfSelectionChange(); return NotifyIMEOfSelectionChange();
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
return NotifyIMEOfUpdateComposition();
default: default:
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
@ -477,6 +481,32 @@ PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
return NS_OK; return NS_OK;
} }
nsresult
PuppetWidget::NotifyIMEOfUpdateComposition()
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
mozilla::TextComposition* textComposition =
nsIMEStateManager::GetTextComposition(this);
NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE);
nsEventStatus status;
uint32_t offset = textComposition->OffsetOfTargetClause();
WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, this);
InitEvent(textRect, nullptr);
textRect.InitForQueryTextRect(offset, 1);
DispatchEvent(&textRect, status);
NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
mTabChild->SendNotifyIMESelectedCompositionRect(offset,
textRect.mReply.mRect);
return NS_OK;
}
nsIMEUpdatePreference nsIMEUpdatePreference
PuppetWidget::GetIMEUpdatePreference() PuppetWidget::GetIMEUpdatePreference()
{ {

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

@ -183,6 +183,7 @@ private:
nsresult IMEEndComposition(bool aCancel); nsresult IMEEndComposition(bool aCancel);
nsresult NotifyIMEOfFocusChange(bool aFocus); nsresult NotifyIMEOfFocusChange(bool aFocus);
nsresult NotifyIMEOfSelectionChange(); nsresult NotifyIMEOfSelectionChange();
nsresult NotifyIMEOfUpdateComposition();
class PaintTask : public nsRunnable { class PaintTask : public nsRunnable {
public: public:

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

@ -76,6 +76,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'../shared', '../shared',
'/dom/events',
'/layout/base', '/layout/base',
'/layout/forms', '/layout/forms',
'/layout/generic', '/layout/generic',