Bug 1166436 part.3 mozilla::ContentCache should store active composition information and TabParent should use them r=m_kato

This commit is contained in:
Masayuki Nakano 2015-06-05 18:28:19 +09:00
parent 8dffab649c
commit 549eff0114
4 changed files with 117 additions and 61 deletions

View File

@ -262,10 +262,6 @@ TabParent::TabParent(nsIContentParent* aManager,
: TabContext(aContext)
, mFrameElement(nullptr)
, mWritingMode()
, mIMEComposing(false)
, mIMECompositionEnding(false)
, mIMEEventCountAfterEnding(0)
, mIMECompositionStart(0)
, mIMECompositionRectOffset(0)
, mRect(0, 0, 0, 0)
, mDimensions(0, 0)
@ -2311,47 +2307,12 @@ TabParent::SendCompositionEvent(WidgetCompositionEvent& event)
return false;
}
if (event.CausesDOMTextEvent()) {
return SendCompositionChangeEvent(event);
}
mIMEComposing = !event.CausesDOMCompositionEndEvent();
mIMECompositionStart = mContentCache.SelectionStart();
if (mIMECompositionEnding) {
mIMEEventCountAfterEnding++;
if (!mContentCache.OnCompositionEvent(event)) {
return true;
}
return PBrowserParent::SendCompositionEvent(event);
}
/**
* During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
* widget usually sends a NS_COMPOSITION_CHANGE event to finalize or
* clear the composition, respectively
*
* Because the event will not reach content in time, we intercept it
* here and pass the text as the EndIMEComposition return value
*/
bool
TabParent::SendCompositionChangeEvent(WidgetCompositionEvent& event)
{
if (mIMECompositionEnding) {
mIMECompositionText = event.mData;
mIMEEventCountAfterEnding++;
return true;
}
// We must be able to simulate the selection because
// we might not receive selection updates in time
if (!mIMEComposing) {
mIMECompositionStart = mContentCache.SelectionStart();
}
mContentCache.SetSelection(mIMECompositionStart + event.mData.Length());
mIMEComposing = !event.CausesDOMCompositionEndEvent();
return PBrowserParent::SendCompositionEvent(event);
}
bool
TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
{
@ -2430,19 +2391,11 @@ TabParent::RecvEndIMEComposition(const bool& aCancel,
nsString* aComposition)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
if (!widget) {
return true;
mIMECompositionEnding = true;
mIMEEventCountAfterEnding = 0;
widget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
REQUEST_TO_COMMIT_COMPOSITION));
mIMECompositionEnding = false;
*aNoCompositionEvent = !mIMEEventCountAfterEnding;
*aComposition = mIMECompositionText;
mIMECompositionText.Truncate(0);
}
*aNoCompositionEvent =
!mContentCache.RequestToCommitComposition(widget, aCancel, *aComposition);
return true;
}

View File

@ -470,8 +470,6 @@ protected:
const int32_t& aX, const int32_t& aY,
const int32_t& aCx, const int32_t& aCy) override;
bool SendCompositionChangeEvent(mozilla::WidgetCompositionEvent& event);
bool InitBrowserConfiguration(const nsCString& aURI,
BrowserConfiguration& aConfiguration);
@ -481,13 +479,6 @@ protected:
static TabParent *mIMETabParent;
ContentCache mContentCache;
mozilla::WritingMode mWritingMode;
bool mIMEComposing;
bool mIMECompositionEnding;
uint32_t mIMEEventCountAfterEnding;
// Buffer to store composition text during ResetInputState
// Compositions in almost all cases are small enough for nsAutoString
nsAutoString mIMECompositionText;
uint32_t mIMECompositionStart;
uint32_t mIMECompositionRectOffset;
InfallibleTArray<LayoutDeviceIntRect> mIMECompositionRects;

View File

@ -6,9 +6,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ContentCache.h"
#include "mozilla/TextEvents.h"
#include "nsIWidget.h"
namespace mozilla {
using namespace widget;
ContentCache::ContentCache()
: mCompositionStart(UINT32_MAX)
, mCompositionEventsDuringRequest(0)
, mIsComposing(false)
, mRequestedToCommitOrCancelComposition(false)
{
}
void
ContentCache::Clear()
{
@ -28,4 +40,65 @@ ContentCache::SetSelection(uint32_t aAnchorOffset, uint32_t aFocusOffset)
mSelection.mFocus = aFocusOffset;
}
bool
ContentCache::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
{
if (!aEvent.CausesDOMTextEvent()) {
MOZ_ASSERT(aEvent.message == NS_COMPOSITION_START);
mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
mCompositionStart = SelectionStart();
// XXX What's this case??
if (mRequestedToCommitOrCancelComposition) {
mCommitStringByRequest = aEvent.mData;
mCompositionEventsDuringRequest++;
return false;
}
return true;
}
// XXX Why do we ignore following composition events here?
// TextComposition must handle following events correctly!
// During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
// widget usually sends a NS_COMPOSITION_CHANGE event to finalize or
// clear the composition, respectively.
// Because the event will not reach content in time, we intercept it
// here and pass the text as the DidRequestToCommitOrCancelComposition()
// return value.
if (mRequestedToCommitOrCancelComposition) {
mCommitStringByRequest = aEvent.mData;
mCompositionEventsDuringRequest++;
return false;
}
// We must be able to simulate the selection because
// we might not receive selection updates in time
if (!mIsComposing) {
mCompositionStart = SelectionStart();
}
// XXX This causes different behavior from non-e10s mode.
// Selection range should represent caret position in the composition
// string but this means selection range is all of the composition string.
SetSelection(mCompositionStart + aEvent.mData.Length());
mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
return true;
}
uint32_t
ContentCache::RequestToCommitComposition(nsIWidget* aWidget,
bool aCancel,
nsAString& aLastString)
{
mRequestedToCommitOrCancelComposition = true;
mCompositionEventsDuringRequest = 0;
aWidget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
REQUEST_TO_COMMIT_COMPOSITION));
mRequestedToCommitOrCancelComposition = false;
aLastString = mCommitStringByRequest;
mCommitStringByRequest.Truncate(0);
return mCompositionEventsDuringRequest;
}
} // namespace mozilla

View File

@ -10,8 +10,12 @@
#include <stdint.h>
#include "mozilla/Assertions.h"
#include "mozilla/EventForwards.h"
#include "nsString.h"
class nsIWidget;
namespace mozilla {
/**
@ -23,12 +27,37 @@ namespace mozilla {
class ContentCache final
{
public:
ContentCache();
void Clear();
void SetText(const nsAString& aText);
const nsString& Text() const { return mText; }
uint32_t TextLength() const { return mText.Length(); }
/**
* OnCompositionEvent() should be called before sending composition string.
* This returns true if the event should be sent. Otherwise, false.
*/
bool OnCompositionEvent(const WidgetCompositionEvent& aCompositionEvent);
/**
* RequestToCommitComposition() requests to commit or cancel composition to
* the widget. If it's handled synchronously, this returns the number of
* composition events after that.
*
* @param aWidget The widget to be requested to commit or cancel
* the composition.
* @param aCancel When the caller tries to cancel the composition, true.
* Otherwise, i.e., tries to commit the composition, false.
* @param aLastString The last composition string before requesting to
* commit or cancel composition.
* @return The count of composition events ignored after a call of
* WillRequestToCommitOrCancelComposition().
*/
uint32_t RequestToCommitComposition(nsIWidget* aWidget,
bool aCancel,
nsAString& aLastString);
void SetSelection(uint32_t aCaretOffset)
{
SetSelection(aCaretOffset, aCaretOffset);
@ -49,6 +78,13 @@ public:
private:
// Whole text in the target
nsString mText;
// This is commit string which is caused by our request.
nsString mCommitStringByRequest;
// Start offset of the composition string.
uint32_t mCompositionStart;
// Count of composition events during requesting commit or cancel the
// composition.
uint32_t mCompositionEventsDuringRequest;
struct Selection final
{
@ -71,6 +107,9 @@ private:
return Reversed() ? mAnchor - mFocus : mFocus - mAnchor;
}
} mSelection;
bool mIsComposing;
bool mRequestedToCommitOrCancelComposition;
};
} // namespace mozilla