gecko/dom/base/TextInputProcessor.h

188 lines
6.0 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_dom_textinputprocessor_h_
#define mozilla_dom_textinputprocessor_h_
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "mozilla/TextEventDispatcher.h"
#include "mozilla/TextEventDispatcherListener.h"
#include "nsAutoPtr.h"
#include "nsITextInputProcessor.h"
#include "nsITextInputProcessorCallback.h"
#include "nsTArray.h"
namespace mozilla {
class TextInputProcessor final : public nsITextInputProcessor
, public widget::TextEventDispatcherListener
{
typedef mozilla::widget::IMENotification IMENotification;
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
public:
TextInputProcessor();
NS_DECL_ISUPPORTS
NS_DECL_NSITEXTINPUTPROCESSOR
// TextEventDispatcherListener
NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
const IMENotification& aNotification) override;
NS_IMETHOD_(void)
OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
protected:
virtual ~TextInputProcessor();
private:
bool IsComposing() const;
nsresult BeginInputTransactionInternal(
mozIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool aForTests,
bool& aSucceeded);
nsresult CommitCompositionInternal(
const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
uint32_t aKeyFlags = 0,
const nsAString* aCommitString = nullptr,
bool* aSucceeded = nullptr);
nsresult CancelCompositionInternal(
const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
uint32_t aKeyFlags = 0);
nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aKeyFlags,
bool aAllowToDispatchKeypress,
uint32_t& aConsumedFlags);
nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aKeyFlags,
bool& aDoDefault);
TextEventDispatcher::DispatchTo GetDispatchTo() const;
nsresult IsValidStateForComposition();
void UnlinkFromTextEventDispatcher();
nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aKeyFlags);
bool IsValidEventTypeForComposition(
const WidgetKeyboardEvent& aKeyboardEvent) const;
nsresult PrepareKeyboardEventForComposition(
nsIDOMKeyEvent* aDOMKeyEvent,
uint32_t& aKeyFlags,
uint8_t aOptionalArgc,
WidgetKeyboardEvent*& aKeyboardEvent);
struct EventDispatcherResult
{
nsresult mResult;
bool mDoDefault;
bool mCanContinue;
EventDispatcherResult()
: mResult(NS_OK)
, mDoDefault(true)
, mCanContinue(true)
{
}
};
EventDispatcherResult MaybeDispatchKeydownForComposition(
const WidgetKeyboardEvent* aKeyboardEvent,
uint32_t aKeyFlags);
EventDispatcherResult MaybeDispatchKeyupForComposition(
const WidgetKeyboardEvent* aKeyboardEvent,
uint32_t aKeyFlags);
/**
* AutoPendingCompositionResetter guarantees to clear all pending composition
* data in its destructor.
*/
class MOZ_STACK_CLASS AutoPendingCompositionResetter
{
public:
explicit AutoPendingCompositionResetter(TextInputProcessor* aTIP);
~AutoPendingCompositionResetter();
private:
RefPtr<TextInputProcessor> mTIP;
};
/**
* TextInputProcessor manages modifier state both with .key and .code.
* For example, left shift key up shouldn't cause inactivating shift state
* while right shift key is being pressed.
*/
struct ModifierKeyData
{
// One of modifier key name
KeyNameIndex mKeyNameIndex;
// Any code name is allowed.
CodeNameIndex mCodeNameIndex;
// A modifier key flag which is activated by the key.
Modifiers mModifier;
explicit ModifierKeyData(const WidgetKeyboardEvent& aKeyboardEvent);
bool operator==(const ModifierKeyData& aOther) const
{
return mKeyNameIndex == aOther.mKeyNameIndex &&
mCodeNameIndex == aOther.mCodeNameIndex;
}
};
class ModifierKeyDataArray : public nsTArray<ModifierKeyData>
{
NS_INLINE_DECL_REFCOUNTING(ModifierKeyDataArray)
public:
Modifiers GetActiveModifiers() const;
void ActivateModifierKey(const ModifierKeyData& aModifierKeyData);
void InactivateModifierKey(const ModifierKeyData& aModifierKeyData);
void ToggleModifierKey(const ModifierKeyData& aModifierKeyData);
private:
virtual ~ModifierKeyDataArray() { }
};
Modifiers GetActiveModifiers() const
{
return mModifierKeyDataArray ?
mModifierKeyDataArray->GetActiveModifiers() : 0;
}
void EnsureModifierKeyDataArray()
{
if (mModifierKeyDataArray) {
return;
}
mModifierKeyDataArray = new ModifierKeyDataArray();
}
void ActivateModifierKey(const ModifierKeyData& aModifierKeyData)
{
EnsureModifierKeyDataArray();
mModifierKeyDataArray->ActivateModifierKey(aModifierKeyData);
}
void InactivateModifierKey(const ModifierKeyData& aModifierKeyData)
{
if (!mModifierKeyDataArray) {
return;
}
mModifierKeyDataArray->InactivateModifierKey(aModifierKeyData);
}
void ToggleModifierKey(const ModifierKeyData& aModifierKeyData)
{
EnsureModifierKeyDataArray();
mModifierKeyDataArray->ToggleModifierKey(aModifierKeyData);
}
TextEventDispatcher* mDispatcher; // [Weak]
nsCOMPtr<nsITextInputProcessorCallback> mCallback;
RefPtr<ModifierKeyDataArray> mModifierKeyDataArray;
bool mForTests;
};
} // namespace mozilla
#endif // #ifndef mozilla_dom_textinputprocessor_h_