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) :
mPresContext(aPresContext), mNode(aNode),
mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
mCompositionStartOffset(0), mCompositionTargetOffset(0),
mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
{
}
@ -36,6 +37,8 @@ TextComposition::TextComposition(const TextComposition& aOther)
mPresContext = aOther.mPresContext;
mNode = aOther.mNode;
mLastData = aOther.mLastData;
mCompositionStartOffset = aOther.mCompositionStartOffset;
mCompositionTargetOffset = aOther.mCompositionTargetOffset;
mIsSynthesizedForTests = aOther.mIsSynthesizedForTests;
}
@ -56,6 +59,51 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
nsEventDispatcher::Dispatch(mNode, mPresContext,
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

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

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

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

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

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

@ -20,6 +20,7 @@ class nsISelection;
namespace mozilla {
class TextCompositionArray;
class TextComposition;
} // namespace mozilla
/*
@ -94,6 +95,11 @@ public:
nsEventStatus* aStatus,
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
* will occur (or not occur).

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

@ -131,6 +131,14 @@ parent:
*/
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
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates

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

@ -992,6 +992,18 @@ TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
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
TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
const uint32_t& aAnchor,

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

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

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

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

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

@ -19,6 +19,8 @@
#include "mozilla/TextEvents.h"
#include "PuppetWidget.h"
#include "nsIWidgetListener.h"
#include "nsIMEStateManager.h"
#include "TextComposition.h"
using namespace mozilla::dom;
using namespace mozilla::hal;
@ -388,6 +390,8 @@ PuppetWidget::NotifyIME(NotificationToIME aNotification)
return NotifyIMEOfFocusChange(false);
case NOTIFY_IME_OF_SELECTION_CHANGE:
return NotifyIMEOfSelectionChange();
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
return NotifyIMEOfUpdateComposition();
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -477,6 +481,32 @@ PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
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
PuppetWidget::GetIMEUpdatePreference()
{

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

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

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

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