mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 917322 part.1 Create mozilla::widget::TextEventDispatcher class r=smaug, sr=smaug
This commit is contained in:
parent
f0c4dad7b8
commit
2e23da33fe
171
widget/TextEventDispatcher.cpp
Normal file
171
widget/TextEventDispatcher.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/TextEventDispatcher.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsView.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
/******************************************************************************
|
||||
* TextEventDispatcher
|
||||
*****************************************************************************/
|
||||
|
||||
TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
, mInitialized(false)
|
||||
, mForTests(false)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mWidget, "aWidget must not be nullptr");
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::Init()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
mInitialized = true;
|
||||
mForTests = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::InitForTests()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
mInitialized = true;
|
||||
mForTests = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::OnDestroyWidget()
|
||||
{
|
||||
mWidget = nullptr;
|
||||
mPendingComposition.Clear();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* TextEventDispatcher::PendingComposition
|
||||
*****************************************************************************/
|
||||
|
||||
TextEventDispatcher::PendingComposition::PendingComposition()
|
||||
{
|
||||
mClauses = new TextRangeArray();
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::PendingComposition::Clear()
|
||||
{
|
||||
mString.Truncate();
|
||||
mClauses->Clear();
|
||||
mCaret.mRangeType = 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::SetString(const nsAString& aString)
|
||||
{
|
||||
mString = aString;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::AppendClause(uint32_t aLength,
|
||||
uint32_t aAttribute)
|
||||
{
|
||||
if (NS_WARN_IF(!aLength)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch (aAttribute) {
|
||||
case NS_TEXTRANGE_RAWINPUT:
|
||||
case NS_TEXTRANGE_SELECTEDRAWTEXT:
|
||||
case NS_TEXTRANGE_CONVERTEDTEXT:
|
||||
case NS_TEXTRANGE_SELECTEDCONVERTEDTEXT: {
|
||||
TextRange textRange;
|
||||
textRange.mStartOffset =
|
||||
mClauses->IsEmpty() ? 0 : mClauses->LastElement().mEndOffset;
|
||||
textRange.mEndOffset = textRange.mStartOffset + aLength;
|
||||
textRange.mRangeType = aAttribute;
|
||||
mClauses->AppendElement(textRange);
|
||||
return NS_OK;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::SetCaret(uint32_t aOffset,
|
||||
uint32_t aLength)
|
||||
{
|
||||
mCaret.mStartOffset = aOffset;
|
||||
mCaret.mEndOffset = mCaret.mStartOffset + aLength;
|
||||
mCaret.mRangeType = NS_TEXTRANGE_CARETPOSITION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::Flush(
|
||||
const TextEventDispatcher* aDispatcher,
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
if (NS_WARN_IF(!aDispatcher->mInitialized)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget(aDispatcher->mWidget);
|
||||
if (NS_WARN_IF(!widget || widget->Destroyed())) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!mClauses->IsEmpty() &&
|
||||
mClauses->LastElement().mEndOffset != mString.Length()) {
|
||||
NS_WARNING("Sum of length of the all clauses must be same as the string "
|
||||
"length");
|
||||
Clear();
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
if (mCaret.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
|
||||
if (mCaret.mEndOffset > mString.Length()) {
|
||||
NS_WARNING("Caret position is out of the composition string");
|
||||
Clear();
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
mClauses->AppendElement(mCaret);
|
||||
}
|
||||
|
||||
WidgetCompositionEvent compChangeEvent(true, NS_COMPOSITION_CHANGE, widget);
|
||||
compChangeEvent.time = PR_IntervalNow();
|
||||
compChangeEvent.mData = mString;
|
||||
if (!mClauses->IsEmpty()) {
|
||||
compChangeEvent.mRanges = mClauses;
|
||||
}
|
||||
|
||||
compChangeEvent.mFlags.mIsSynthesizedForTests = aDispatcher->mForTests;
|
||||
|
||||
nsresult rv = widget->DispatchEvent(&compChangeEvent, aStatus);
|
||||
Clear();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
148
widget/TextEventDispatcher.h
Normal file
148
widget/TextEventDispatcher.h
Normal file
@ -0,0 +1,148 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_textcompositionsynthesizer_h_
|
||||
#define mozilla_textcompositionsynthesizer_h_
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TextRange.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
/**
|
||||
* TextEventDispatcher is a helper class for dispatching widget events defined
|
||||
* in TextEvents.h. Currently, this is a helper for dispatching
|
||||
* WidgetCompositionEvent. However, WidgetKeyboardEvent and/or
|
||||
* WidgetQueryContentEvent may be supported by this class in the future.
|
||||
* An instance of this class is created by nsIWidget instance and owned by it.
|
||||
* This is typically created only by the top level widgets because only they
|
||||
* handle IME.
|
||||
*/
|
||||
|
||||
class TextEventDispatcher MOZ_FINAL
|
||||
{
|
||||
~TextEventDispatcher()
|
||||
{
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(TextEventDispatcher)
|
||||
|
||||
public:
|
||||
explicit TextEventDispatcher(nsIWidget* aWidget);
|
||||
|
||||
/**
|
||||
* Initializes the instance for IME or automated test. Either IME or tests
|
||||
* need to call one of them before starting composition every time. If they
|
||||
* return NS_ERROR_ALREADY_INITIALIZED, it means that another IME composes
|
||||
* with the instance. Then, the caller shouldn't start composition.
|
||||
*/
|
||||
nsresult Init();
|
||||
nsresult InitForTests();
|
||||
|
||||
/**
|
||||
* OnDestroyWidget() is called when mWidget is being destroyed.
|
||||
*/
|
||||
void OnDestroyWidget();
|
||||
|
||||
/**
|
||||
* SetPendingCompositionString() sets new composition string which will be
|
||||
* dispatched with NS_COMPOSITION_CHANGE event by calling Flush().
|
||||
*
|
||||
* @param aString New composition string.
|
||||
*/
|
||||
nsresult SetPendingCompositionString(const nsAString& aString)
|
||||
{
|
||||
return mPendingComposition.SetString(aString);
|
||||
}
|
||||
|
||||
/**
|
||||
* AppendClauseToPendingComposition() appends a clause information to
|
||||
* the pending composition string.
|
||||
*
|
||||
* @param aLength Length of the clause.
|
||||
* @param aAttribute One of NS_TEXTRANGE_RAWINPUT,
|
||||
* NS_TEXTRANGE_SELECTEDRAWTEXT,
|
||||
* NS_TEXTRANGE_CONVERTEDTEXT or
|
||||
* NS_TEXTRANGE_SELECTEDCONVERTEDTEXT.
|
||||
*/
|
||||
nsresult AppendClauseToPendingComposition(uint32_t aLength,
|
||||
uint32_t aAttribute)
|
||||
{
|
||||
return mPendingComposition.AppendClause(aLength, aAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* SetCaretInPendingComposition() sets caret position in the pending
|
||||
* composition string and its length. This is optional. If IME doesn't
|
||||
* want to show caret, it shouldn't need to call this.
|
||||
*
|
||||
* @param aOffset Offset of the caret in the pending composition
|
||||
* string. This should not be larger than the length
|
||||
* of the pending composition string.
|
||||
* @param aLength Caret width. If this is 0, caret will be collapsed.
|
||||
* Note that Gecko doesn't supported wide caret yet,
|
||||
* therefore, this is ignored for now.
|
||||
*/
|
||||
nsresult SetCaretInPendingComposition(uint32_t aOffset,
|
||||
uint32_t aLength)
|
||||
{
|
||||
return mPendingComposition.SetCaret(aOffset, aLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* FlushPendingComposition() sends the pending composition string
|
||||
* to the widget of the store DOM window. Before calling this, IME needs to
|
||||
* set pending composition string with SetPendingCompositionString(),
|
||||
* AppendClauseToPendingComposition() and/or
|
||||
* SetCaretInPendingComposition().
|
||||
*/
|
||||
nsresult FlushPendingComposition(nsEventStatus& aStatus)
|
||||
{
|
||||
return mPendingComposition.Flush(this, aStatus);
|
||||
}
|
||||
|
||||
private:
|
||||
// mWidget is owner of the instance. When this is created, this is set.
|
||||
// And when mWidget is released, this is cleared by OnDestroyWidget().
|
||||
// Note that mWidget may be destroyed already (i.e., mWidget->Destroyed() may
|
||||
// return true).
|
||||
nsIWidget* mWidget;
|
||||
|
||||
// mPendingComposition stores new composition string temporarily.
|
||||
// These values will be used for dispatching NS_COMPOSITION_CHANGE event
|
||||
// in Flush(). When Flush() is called, the members will be cleared
|
||||
// automatically.
|
||||
class PendingComposition
|
||||
{
|
||||
public:
|
||||
PendingComposition();
|
||||
nsresult SetString(const nsAString& aString);
|
||||
nsresult AppendClause(uint32_t aLength, uint32_t aAttribute);
|
||||
nsresult SetCaret(uint32_t aOffset, uint32_t aLength);
|
||||
nsresult Flush(const TextEventDispatcher* aDispatcher,
|
||||
nsEventStatus& aStatus);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
nsAutoString mString;
|
||||
nsRefPtr<TextRangeArray> mClauses;
|
||||
TextRange mCaret;
|
||||
};
|
||||
PendingComposition mPendingComposition;
|
||||
|
||||
bool mInitialized;
|
||||
bool mForTests;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_widget_textcompositionsynthesizer_h_
|
@ -120,6 +120,7 @@ EXPORTS.mozilla += [
|
||||
'LookAndFeel.h',
|
||||
'MiscEvents.h',
|
||||
'MouseEvents.h',
|
||||
'TextEventDispatcher.h',
|
||||
'TextEvents.h',
|
||||
'TextRange.h',
|
||||
'TouchEvents.h',
|
||||
@ -156,6 +157,7 @@ UNIFIED_SOURCES += [
|
||||
'PuppetWidget.cpp',
|
||||
'ScreenProxy.cpp',
|
||||
'SharedWidgetUtils.cpp',
|
||||
'TextEventDispatcher.cpp',
|
||||
'VsyncDispatcher.cpp',
|
||||
'WidgetEventImpl.cpp',
|
||||
'WidgetUtils.cpp',
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/TextEventDispatcher.h"
|
||||
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
@ -1139,6 +1140,12 @@ void nsBaseWidget::OnDestroy()
|
||||
{
|
||||
// release references to device context and app shell
|
||||
NS_IF_RELEASE(mContext);
|
||||
|
||||
if (mTextEventDispatcher) {
|
||||
mTextEventDispatcher->OnDestroyWidget();
|
||||
// Don't release it until this widget actually released because after this
|
||||
// is called, TextEventDispatcher() may create it again.
|
||||
}
|
||||
}
|
||||
|
||||
NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
|
||||
@ -1578,6 +1585,15 @@ nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIWidget::TextEventDispatcher*)
|
||||
nsBaseWidget::GetTextEventDispatcher()
|
||||
{
|
||||
if (!mTextEventDispatcher) {
|
||||
mTextEventDispatcher = new TextEventDispatcher(this);
|
||||
}
|
||||
return mTextEventDispatcher;
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
|
||||
a11y::Accessible*
|
||||
|
@ -221,6 +221,7 @@ public:
|
||||
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) MOZ_OVERRIDE;
|
||||
NS_IMETHOD RegisterTouchWindow() MOZ_OVERRIDE;
|
||||
NS_IMETHOD UnregisterTouchWindow() MOZ_OVERRIDE;
|
||||
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() MOZ_OVERRIDE MOZ_FINAL;
|
||||
|
||||
void NotifyWindowDestroyed();
|
||||
void NotifySizeMoveDone();
|
||||
@ -428,6 +429,7 @@ protected:
|
||||
nsRefPtr<mozilla::CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
|
||||
nsRefPtr<APZCTreeManager> mAPZC;
|
||||
nsRefPtr<WidgetShutdownObserver> mShutdownObserver;
|
||||
nsRefPtr<TextEventDispatcher> mTextEventDispatcher;
|
||||
nsCursor mCursor;
|
||||
bool mUpdateCursor;
|
||||
nsBorderStyle mBorderStyle;
|
||||
|
@ -53,6 +53,9 @@ class PLayerTransactionChild;
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
}
|
||||
namespace widget {
|
||||
class TextEventDispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,8 +107,8 @@ typedef void* nsNativeWidget;
|
||||
#endif
|
||||
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0x13239ca, 0xaf3f, 0x4f27, \
|
||||
{ 0xaf, 0x83, 0x47, 0xa9, 0x82, 0x3d, 0x99, 0xee } };
|
||||
{ 0x029a269f, 0x8b1a, 0x466b, \
|
||||
{ 0x89, 0x61, 0xc9, 0xcd, 0x23, 0x4e, 0x21, 0x27 } };
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
@ -727,6 +730,7 @@ class nsIWidget : public nsISupports {
|
||||
typedef mozilla::widget::InputContext InputContext;
|
||||
typedef mozilla::widget::InputContextAction InputContextAction;
|
||||
typedef mozilla::widget::SizeConstraints SizeConstraints;
|
||||
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
|
||||
typedef mozilla::CompositorVsyncDispatcher CompositorVsyncDispatcher;
|
||||
|
||||
// Used in UpdateThemeGeometries.
|
||||
@ -2200,6 +2204,12 @@ public:
|
||||
*/
|
||||
virtual int32_t RoundsWidgetCoordinatesTo() { return 1; }
|
||||
|
||||
/**
|
||||
* GetTextEventDispatcher() returns TextEventDispatcher belonging to the
|
||||
* widget. Note that this never returns nullptr.
|
||||
*/
|
||||
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Like GetDefaultScale, but taking into account only the system settings
|
||||
|
Loading…
Reference in New Issue
Block a user