зеркало из 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) :
|
||||
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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче