gecko/widget/TextEvents.h
Ryan VanderMeulen 77e8bee35e Backed out 6 changesets (bug 989198, bug 1082963) for causing bug 1083231.
Backed out changeset a7c972407578 (bug 1082963)
Backed out changeset 94d1b30bde00 (bug 989198)
Backed out changeset 01e064ceb505 (bug 989198)
Backed out changeset f5a538109e36 (bug 989198)
Backed out changeset 3ff227d79d74 (bug 989198)
Backed out changeset 186743fc6f6d (bug 989198)

CLOSED TREE
2014-10-16 12:57:18 -04:00

531 lines
15 KiB
C++

/* -*- 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_TextEvents_h__
#define mozilla_TextEvents_h__
#include <stdint.h>
#include "mozilla/Assertions.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/EventForwards.h" // for KeyNameIndex, temporarily
#include "mozilla/TextRange.h"
#include "nsCOMPtr.h"
#include "nsIDOMKeyEvent.h"
#include "nsITransferable.h"
#include "nsRect.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
/******************************************************************************
* virtual keycode values
******************************************************************************/
#define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) NS_##aDOMKeyName = aDOMKeyCode
enum
{
#include "mozilla/VirtualKeyCodeList.h"
};
#undef NS_DEFINE_VK
#define kLatestSeqno UINT32_MAX
namespace mozilla {
namespace dom {
class PBrowserParent;
class PBrowserChild;
} // namespace dom
namespace plugins {
class PPluginInstanceChild;
} // namespace plugins
/******************************************************************************
* mozilla::AlternativeCharCode
*
* This stores alternative charCode values of a key event with some modifiers.
* The stored values proper for testing shortcut key or access key.
******************************************************************************/
struct AlternativeCharCode
{
AlternativeCharCode() :
mUnshiftedCharCode(0), mShiftedCharCode(0)
{
}
AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
{
}
uint32_t mUnshiftedCharCode;
uint32_t mShiftedCharCode;
};
/******************************************************************************
* mozilla::WidgetKeyboardEvent
******************************************************************************/
class WidgetKeyboardEvent : public WidgetInputEvent
{
private:
friend class dom::PBrowserParent;
friend class dom::PBrowserChild;
WidgetKeyboardEvent()
{
}
public:
virtual WidgetKeyboardEvent* AsKeyboardEvent() MOZ_OVERRIDE { return this; }
WidgetKeyboardEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
: WidgetInputEvent(aIsTrusted, aMessage, aWidget, eKeyboardEventClass)
, keyCode(0)
, charCode(0)
, location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD)
, isChar(false)
, mIsRepeat(false)
, mIsComposing(false)
, mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
, mNativeKeyEvent(nullptr)
, mUniqueId(0)
{
}
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
{
MOZ_ASSERT(mClass == eKeyboardEventClass,
"Duplicate() must be overridden by sub class");
// Not copying widget, it is a weak reference.
WidgetKeyboardEvent* result =
new WidgetKeyboardEvent(false, message, nullptr);
result->AssignKeyEventData(*this, true);
result->mFlags = mFlags;
return result;
}
// A DOM keyCode value or 0. If a keypress event whose charCode is 0, this
// should be 0.
uint32_t keyCode;
// If the instance is a keypress event of a printable key, this is a UTF-16
// value of the key. Otherwise, 0. This value must not be a control
// character when some modifiers are active. Then, this value should be an
// unmodified value except Shift and AltGr.
uint32_t charCode;
// One of nsIDOMKeyEvent::DOM_KEY_LOCATION_*
uint32_t location;
// OS translated Unicode chars which are used for accesskey and accelkey
// handling. The handlers will try from first character to last character.
nsTArray<AlternativeCharCode> alternativeCharCodes;
// Indicates whether the event signifies a printable character
bool isChar;
// Indicates whether the event is generated by auto repeat or not.
// if this is keyup event, always false.
bool mIsRepeat;
// Indicates whether the event is generated during IME (or deadkey)
// composition. This is initialized by EventStateManager. So, key event
// dispatchers don't need to initialize this.
bool mIsComposing;
// DOM KeyboardEvent.key
KeyNameIndex mKeyNameIndex;
// DOM KeyboardEvent.code
CodeNameIndex mCodeNameIndex;
// DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
nsString mKeyValue;
// DOM KeyboardEvent.code only when mCodeNameIndex is
// CODE_NAME_INDEX_USE_STRING.
nsString mCodeValue;
// OS-specific native event can optionally be preserved
void* mNativeKeyEvent;
// Unique id associated with a keydown / keypress event. Used in identifing
// keypress events for removal from async event dispatch queue in metrofx
// after preventDefault is called on keydown events. It's ok if this wraps
// over long periods.
uint32_t mUniqueId;
void GetDOMKeyName(nsAString& aKeyName)
{
if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
aKeyName = mKeyValue;
return;
}
GetDOMKeyName(mKeyNameIndex, aKeyName);
}
void GetDOMCodeName(nsAString& aCodeName)
{
if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
aCodeName = mCodeValue;
return;
}
GetDOMCodeName(mCodeNameIndex, aCodeName);
}
static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
nsAString& aKeyName);
static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
nsAString& aCodeName);
static const char* GetCommandStr(Command aCommand);
void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
{
AssignInputEventData(aEvent, aCopyTargets);
keyCode = aEvent.keyCode;
charCode = aEvent.charCode;
location = aEvent.location;
alternativeCharCodes = aEvent.alternativeCharCodes;
isChar = aEvent.isChar;
mIsRepeat = aEvent.mIsRepeat;
mIsComposing = aEvent.mIsComposing;
mKeyNameIndex = aEvent.mKeyNameIndex;
mCodeNameIndex = aEvent.mCodeNameIndex;
mKeyValue = aEvent.mKeyValue;
mCodeValue = aEvent.mCodeValue;
// Don't copy mNativeKeyEvent because it may be referred after its instance
// is destroyed.
mNativeKeyEvent = nullptr;
mUniqueId = aEvent.mUniqueId;
}
};
/******************************************************************************
* mozilla::WidgetCompositionEvent
******************************************************************************/
class WidgetCompositionEvent : public WidgetGUIEvent
{
private:
friend class mozilla::dom::PBrowserParent;
friend class mozilla::dom::PBrowserChild;
WidgetCompositionEvent()
: mSeqno(kLatestSeqno)
{
}
public:
uint32_t mSeqno;
public:
virtual WidgetCompositionEvent* AsCompositionEvent() MOZ_OVERRIDE
{
return this;
}
WidgetCompositionEvent(bool aIsTrusted, uint32_t aMessage,
nsIWidget* aWidget)
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
, mSeqno(kLatestSeqno)
{
// XXX compositionstart is cancelable in draft of DOM3 Events.
// However, it doesn't make sense for us, we cannot cancel composition
// when we send compositionstart event.
mFlags.mCancelable = false;
}
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
{
MOZ_ASSERT(mClass == eCompositionEventClass,
"Duplicate() must be overridden by sub class");
// Not copying widget, it is a weak reference.
WidgetCompositionEvent* result =
new WidgetCompositionEvent(false, message, nullptr);
result->AssignCompositionEventData(*this, true);
result->mFlags = mFlags;
return result;
}
// The composition string or the commit string. If the instance is a
// compositionstart event, this is initialized with selected text by
// TextComposition automatically.
nsString mData;
nsRefPtr<TextRangeArray> mRanges;
void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
bool aCopyTargets)
{
AssignGUIEventData(aEvent, aCopyTargets);
mData = aEvent.mData;
// Currently, we don't need to copy the other members because they are
// for internal use only (not available from JS).
}
bool IsComposing() const
{
return mRanges && mRanges->IsComposing();
}
uint32_t TargetClauseOffset() const
{
return mRanges ? mRanges->TargetClauseOffset() : 0;
}
uint32_t RangeCount() const
{
return mRanges ? mRanges->Length() : 0;
}
};
/******************************************************************************
* mozilla::WidgetQueryContentEvent
******************************************************************************/
class WidgetQueryContentEvent : public WidgetGUIEvent
{
private:
friend class dom::PBrowserParent;
friend class dom::PBrowserChild;
WidgetQueryContentEvent()
{
MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
}
public:
virtual WidgetQueryContentEvent* AsQueryContentEvent() MOZ_OVERRIDE
{
return this;
}
WidgetQueryContentEvent(bool aIsTrusted, uint32_t aMessage,
nsIWidget* aWidget)
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
, mSucceeded(false)
, mWasAsync(false)
, mUseNativeLineBreak(true)
{
}
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
{
// This event isn't an internal event of any DOM event.
NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
"WidgetQueryContentEvent needs to support Duplicate()");
MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
return nullptr;
}
void InitForQueryTextContent(uint32_t aOffset, uint32_t aLength,
bool aUseNativeLineBreak = true)
{
NS_ASSERTION(message == NS_QUERY_TEXT_CONTENT,
"wrong initializer is called");
mInput.mOffset = aOffset;
mInput.mLength = aLength;
mUseNativeLineBreak = aUseNativeLineBreak;
}
void InitForQueryCaretRect(uint32_t aOffset,
bool aUseNativeLineBreak = true)
{
NS_ASSERTION(message == NS_QUERY_CARET_RECT,
"wrong initializer is called");
mInput.mOffset = aOffset;
mUseNativeLineBreak = aUseNativeLineBreak;
}
void InitForQueryTextRect(uint32_t aOffset, uint32_t aLength,
bool aUseNativeLineBreak = true)
{
NS_ASSERTION(message == NS_QUERY_TEXT_RECT,
"wrong initializer is called");
mInput.mOffset = aOffset;
mInput.mLength = aLength;
mUseNativeLineBreak = aUseNativeLineBreak;
}
void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
{
NS_ASSERTION(message == NS_QUERY_DOM_WIDGET_HITTEST,
"wrong initializer is called");
refPoint = aPoint;
}
uint32_t GetSelectionStart(void) const
{
NS_ASSERTION(message == NS_QUERY_SELECTED_TEXT,
"not querying selection");
return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
}
uint32_t GetSelectionEnd(void) const
{
NS_ASSERTION(message == NS_QUERY_SELECTED_TEXT,
"not querying selection");
return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
}
bool mSucceeded;
bool mWasAsync;
bool mUseNativeLineBreak;
struct
{
uint32_t mOffset;
uint32_t mLength;
} mInput;
struct
{
void* mContentsRoot;
uint32_t mOffset;
nsString mString;
// Finally, the coordinates is system coordinates.
nsIntRect mRect;
// The return widget has the caret. This is set at all query events.
nsIWidget* mFocusedWidget;
// true if selection is reversed (end < start)
bool mReversed;
// true if the selection exists
bool mHasSelection;
// true if DOM element under mouse belongs to widget
bool mWidgetIsHit;
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
nsCOMPtr<nsITransferable> mTransferable;
} mReply;
enum
{
NOT_FOUND = UINT32_MAX
};
// values of mComputedScrollAction
enum
{
SCROLL_ACTION_NONE,
SCROLL_ACTION_LINE,
SCROLL_ACTION_PAGE
};
};
/******************************************************************************
* mozilla::WidgetSelectionEvent
******************************************************************************/
class WidgetSelectionEvent : public WidgetGUIEvent
{
private:
friend class mozilla::dom::PBrowserParent;
friend class mozilla::dom::PBrowserChild;
WidgetSelectionEvent()
: mSeqno(kLatestSeqno)
, mOffset(0)
, mLength(0)
, mReversed(false)
, mExpandToClusterBoundary(true)
, mSucceeded(false)
{
}
public:
uint32_t mSeqno;
public:
virtual WidgetSelectionEvent* AsSelectionEvent() MOZ_OVERRIDE
{
return this;
}
WidgetSelectionEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
, mSeqno(kLatestSeqno)
, mOffset(0)
, mLength(0)
, mReversed(false)
, mExpandToClusterBoundary(true)
, mSucceeded(false)
, mUseNativeLineBreak(true)
{
}
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
{
// This event isn't an internal event of any DOM event.
NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
"WidgetSelectionEvent needs to support Duplicate()");
MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
return nullptr;
}
// Start offset of selection
uint32_t mOffset;
// Length of selection
uint32_t mLength;
// Selection "anchor" should be in front
bool mReversed;
// Cluster-based or character-based
bool mExpandToClusterBoundary;
// true if setting selection succeeded.
bool mSucceeded;
// true if native line breaks are used for mOffset and mLength
bool mUseNativeLineBreak;
};
/******************************************************************************
* mozilla::InternalEditorInputEvent
******************************************************************************/
class InternalEditorInputEvent : public InternalUIEvent
{
private:
InternalEditorInputEvent()
: mIsComposing(false)
{
}
public:
virtual InternalEditorInputEvent* AsEditorInputEvent() MOZ_OVERRIDE
{
return this;
}
InternalEditorInputEvent(bool aIsTrusted, uint32_t aMessage,
nsIWidget* aWidget)
: InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
, mIsComposing(false)
{
if (!aIsTrusted) {
mFlags.mBubbles = false;
mFlags.mCancelable = false;
return;
}
mFlags.mBubbles = true;
mFlags.mCancelable = false;
}
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
{
MOZ_ASSERT(mClass == eEditorInputEventClass,
"Duplicate() must be overridden by sub class");
// Not copying widget, it is a weak reference.
InternalEditorInputEvent* result =
new InternalEditorInputEvent(false, message, nullptr);
result->AssignEditorInputEventData(*this, true);
result->mFlags = mFlags;
return result;
}
bool mIsComposing;
void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
bool aCopyTargets)
{
AssignUIEventData(aEvent, aCopyTargets);
mIsComposing = aEvent.mIsComposing;
}
};
} // namespace mozilla
#endif // mozilla_TextEvents_h__