зеркало из https://github.com/mozilla/gecko-dev.git
Bug 935821 - Part 1. Notify IME Compostion to widget. r=masayuki
This commit is contained in:
Родитель
446f6a3744
Коммит
1eaa8a3e12
|
@ -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',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче