Bug 1130935 part.6 Selection change notification should have selection range and writing mode information r=smaug

This commit is contained in:
Masayuki Nakano 2015-05-15 10:18:08 +09:00
parent 0b3b4199a3
commit 819a662e1b
8 changed files with 131 additions and 22 deletions

View File

@ -32,6 +32,7 @@
#include "nsPresContext.h"
#include "nsThreadUtils.h"
#include "nsWeakReference.h"
#include "WritingModes.h"
namespace mozilla {
@ -247,6 +248,12 @@ IMEContentObserver::UnregisterObservers(bool aPostEvent)
}
}
nsPresContext*
IMEContentObserver::GetPresContext() const
{
return mESM ? mESM->GetPresContext() : nullptr;
}
void
IMEContentObserver::Destroy()
{
@ -331,12 +338,39 @@ public:
NS_IMETHOD Run()
{
if (mDispatcher->GetWidget()) {
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mCausedByComposition =
mCausedByComposition;
mDispatcher->GetWidget()->NotifyIME(notification);
nsCOMPtr<nsIWidget> widget = mDispatcher->GetWidget();
nsPresContext* presContext = mDispatcher->GetPresContext();
if (!widget || !presContext) {
return NS_OK;
}
// XXX Cannot we cache some information for reducing the cost to compute
// selection offset and writing mode?
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT, widget);
ContentEventHandler handler(presContext);
handler.OnQuerySelectedText(&selection);
if (NS_WARN_IF(!selection.mSucceeded)) {
return NS_OK;
}
// The widget might be destroyed during querying the content since it
// causes flushing layout.
widget = mDispatcher->GetWidget();
if (!widget || NS_WARN_IF(widget->Destroyed())) {
return NS_OK;
}
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mOffset =
selection.mReply.mOffset;
notification.mSelectionChangeData.mLength =
selection.mReply.mString.Length();
notification.mSelectionChangeData.SetWritingMode(
selection.GetWritingMode());
notification.mSelectionChangeData.mReversed = selection.mReply.mReversed;
notification.mSelectionChangeData.mCausedByComposition =
mCausedByComposition;
widget->NotifyIME(notification);
return NS_OK;
}

View File

@ -79,6 +79,7 @@ public:
return mUpdatePreference.WantDuringDeactive();
}
nsIWidget* GetWidget() const { return mWidget; }
nsPresContext* GetPresContext() const;
nsresult GetSelectionAndRoot(nsISelection** aSelection,
nsIContent** aRoot) const;

View File

@ -1894,6 +1894,15 @@ TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
(updatePreference.WantChangesCausedByComposition() ||
!aCausedByComposition)) {
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mOffset =
std::min(mIMESelectionAnchor, mIMESelectionFocus);
notification.mSelectionChangeData.mLength =
mIMESelectionAnchor > mIMESelectionFocus ?
mIMESelectionAnchor - mIMESelectionFocus :
mIMESelectionFocus - mIMESelectionAnchor;
notification.mSelectionChangeData.mReversed =
mIMESelectionFocus < mIMESelectionAnchor;
notification.mSelectionChangeData.SetWritingMode(mWritingMode);
notification.mSelectionChangeData.mCausedByComposition =
aCausedByComposition;
widget->NotifyIME(notification);

View File

@ -30,6 +30,10 @@
namespace mozilla {
namespace widget {
struct IMENotification;
} // namespace widget
// Physical axis constants.
enum PhysicalAxis {
eAxisVertical = 0x0,
@ -475,6 +479,10 @@ private:
friend class LogicalRect;
friend struct IPC::ParamTraits<WritingMode>;
// IMENotification cannot store this class directly since this has some
// constructors. Therefore, it stores mWritingMode and recreate the
// instance from it.
friend struct widget::IMENotification;
/**
* Return a WritingMode representing an unknown value.

View File

@ -886,19 +886,12 @@ PuppetWidget::NotifyIMEOfSelectionChange(
if (!mTabChild)
return NS_ERROR_FAILURE;
nsEventStatus status;
WidgetQueryContentEvent queryEvent(true, NS_QUERY_SELECTED_TEXT, this);
InitEvent(queryEvent, nullptr);
DispatchEvent(&queryEvent, status);
if (queryEvent.mSucceeded) {
mTabChild->SendNotifyIMESelection(
mIMELastReceivedSeqno,
queryEvent.GetSelectionStart(),
queryEvent.GetSelectionEnd(),
queryEvent.GetWritingMode(),
aIMENotification.mSelectionChangeData.mCausedByComposition);
}
mTabChild->SendNotifyIMESelection(
mIMELastReceivedSeqno,
aIMENotification.mSelectionChangeData.StartOffset(),
aIMENotification.mSelectionChangeData.EndOffset(),
aIMENotification.mSelectionChangeData.GetWritingMode(),
aIMENotification.mSelectionChangeData.mCausedByComposition);
return NS_OK;
}

View File

@ -54,6 +54,7 @@
#include "mozilla/dom/TabParent.h"
#include "nsRefPtrHashtable.h"
#include "TouchEvents.h"
#include "WritingModes.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#endif
@ -98,6 +99,25 @@ int32_t nsIWidget::sPointerIdCounter = 0;
/*static*/ uint64_t AutoObserverNotifier::sObserverId = 0;
/*static*/ nsDataHashtable<nsUint64HashKey, nsCOMPtr<nsIObserver>> AutoObserverNotifier::sSavedObservers;
namespace mozilla {
namespace widget {
void
IMENotification::SelectionChangeData::SetWritingMode(
const WritingMode& aWritingMode)
{
mWritingMode = aWritingMode.mWritingMode;
}
WritingMode
IMENotification::SelectionChangeData::GetWritingMode() const
{
return WritingMode(mWritingMode);
}
} // namespace widget
} // namespace mozilla
nsAutoRollup::nsAutoRollup()
{
// remember if mLastRollup was null, and only clear it upon destruction

View File

@ -675,6 +675,10 @@ struct ParamTraits<mozilla::widget::IMENotification>
static_cast<mozilla::widget::IMEMessageType>(aParam.mMessage));
switch (aParam.mMessage) {
case mozilla::widget::NOTIFY_IME_OF_SELECTION_CHANGE:
WriteParam(aMsg, aParam.mSelectionChangeData.mOffset);
WriteParam(aMsg, aParam.mSelectionChangeData.mLength);
WriteParam(aMsg, aParam.mSelectionChangeData.mWritingMode);
WriteParam(aMsg, aParam.mSelectionChangeData.mReversed);
WriteParam(aMsg, aParam.mSelectionChangeData.mCausedByComposition);
return;
case mozilla::widget::NOTIFY_IME_OF_TEXT_CHANGE:
@ -711,6 +715,14 @@ struct ParamTraits<mozilla::widget::IMENotification>
switch (aResult->mMessage) {
case mozilla::widget::NOTIFY_IME_OF_SELECTION_CHANGE:
return ReadParam(aMsg, aIter,
&aResult->mSelectionChangeData.mOffset) &&
ReadParam(aMsg, aIter,
&aResult->mSelectionChangeData.mLength) &&
ReadParam(aMsg, aIter,
&aResult->mSelectionChangeData.mWritingMode) &&
ReadParam(aMsg, aIter,
&aResult->mSelectionChangeData.mReversed) &&
ReadParam(aMsg, aIter,
&aResult->mSelectionChangeData.mCausedByComposition);
case mozilla::widget::NOTIFY_IME_OF_TEXT_CHANGE:
return ReadParam(aMsg, aIter,

View File

@ -38,6 +38,7 @@ class nsIScreen;
namespace mozilla {
class CompositorVsyncDispatcher;
class WritingMode;
namespace dom {
class TabChild;
}
@ -595,6 +596,10 @@ struct IMENotification
{
switch (aMessage) {
case NOTIFY_IME_OF_SELECTION_CHANGE:
mSelectionChangeData.mOffset = UINT32_MAX;
mSelectionChangeData.mLength = 0;
mSelectionChangeData.mWritingMode = 0;
mSelectionChangeData.mReversed = false;
mSelectionChangeData.mCausedByComposition = false;
break;
case NOTIFY_IME_OF_TEXT_CHANGE:
@ -618,13 +623,40 @@ struct IMENotification
IMEMessage mMessage;
// NOTIFY_IME_OF_SELECTION_CHANGE specific data
struct SelectionChangeData
{
// Selection range.
uint32_t mOffset;
uint32_t mLength;
// Writing mode at the selection.
uint8_t mWritingMode;
bool mReversed;
bool mCausedByComposition;
void SetWritingMode(const WritingMode& aWritingMode);
WritingMode GetWritingMode() const;
uint32_t StartOffset() const
{
return mOffset + (mReversed ? mLength : 0);
}
uint32_t EndOffset() const
{
return mOffset + (mReversed ? 0 : mLength);
}
bool IsInInt32Range() const
{
return mOffset + mLength <= INT32_MAX;
}
};
union
{
// NOTIFY_IME_OF_SELECTION_CHANGE specific data
struct
{
bool mCausedByComposition;
} mSelectionChangeData;
SelectionChangeData mSelectionChangeData;
// NOTIFY_IME_OF_TEXT_CHANGE specific data
struct