summaryrefslogtreecommitdiff
path: root/widget/cocoa/TextInputHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/cocoa/TextInputHandler.h')
-rw-r--r--widget/cocoa/TextInputHandler.h1194
1 files changed, 0 insertions, 1194 deletions
diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h
deleted file mode 100644
index 86da354abb..0000000000
--- a/widget/cocoa/TextInputHandler.h
+++ /dev/null
@@ -1,1194 +0,0 @@
-/* -*- 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 TextInputHandler_h_
-#define TextInputHandler_h_
-
-#include "nsCocoaUtils.h"
-
-#import <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-#include "mozView.h"
-#include "nsString.h"
-#include "nsCOMPtr.h"
-#include "nsITimer.h"
-#include "nsTArray.h"
-#include "mozilla/EventForwards.h"
-#include "mozilla/TextEventDispatcherListener.h"
-#include "WritingModes.h"
-
-class nsChildView;
-
-namespace mozilla {
-namespace widget {
-
-// Key code constants
-enum
-{
-#if !defined(MAC_OS_X_VERSION_10_12) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
- kVK_RightCommand = 0x36, // right command key
-#endif
-
- kVK_PC_PrintScreen = kVK_F13,
- kVK_PC_ScrollLock = kVK_F14,
- kVK_PC_Pause = kVK_F15,
-
- kVK_PC_Insert = kVK_Help,
- kVK_PC_Backspace = kVK_Delete,
- kVK_PC_Delete = kVK_ForwardDelete,
-
- kVK_PC_ContextMenu = 0x6E,
-
- kVK_Powerbook_KeypadEnter = 0x34 // Enter on Powerbook's keyboard is different
-};
-
-/**
- * TISInputSourceWrapper is a wrapper for the TISInputSourceRef. If we get the
- * TISInputSourceRef from InputSourceID, we need to release the CFArray instance
- * which is returned by TISCreateInputSourceList. However, when we release the
- * list, we cannot access the TISInputSourceRef. So, it's not usable, and it
- * may cause the memory leak bugs. nsTISInputSource automatically releases the
- * list when the instance is destroyed.
- */
-class TISInputSourceWrapper
-{
-public:
- static TISInputSourceWrapper& CurrentInputSource();
- /**
- * Shutdown() should be called when nobody doesn't need to use this class.
- */
- static void Shutdown();
-
- TISInputSourceWrapper()
- {
- mInputSourceList = nullptr;
- Clear();
- }
-
- explicit TISInputSourceWrapper(const char* aID)
- {
- mInputSourceList = nullptr;
- InitByInputSourceID(aID);
- }
-
- explicit TISInputSourceWrapper(SInt32 aLayoutID)
- {
- mInputSourceList = nullptr;
- InitByLayoutID(aLayoutID);
- }
-
- explicit TISInputSourceWrapper(TISInputSourceRef aInputSource)
- {
- mInputSourceList = nullptr;
- InitByTISInputSourceRef(aInputSource);
- }
-
- ~TISInputSourceWrapper() { Clear(); }
-
- void InitByInputSourceID(const char* aID);
- void InitByInputSourceID(const nsAFlatString &aID);
- void InitByInputSourceID(const CFStringRef aID);
- /**
- * InitByLayoutID() initializes the keyboard layout by the layout ID.
- *
- * @param aLayoutID An ID of keyboard layout.
- * 0: US
- * 1: Greek
- * 2: German
- * 3: Swedish-Pro
- * 4: Dvorak-Qwerty Cmd
- * 5: Thai
- * 6: Arabic
- * 7: French
- * 8: Hebrew
- * 9: Lithuanian
- * 10: Norwegian
- * 11: Spanish
- * @param aOverrideKeyboard When testing set to TRUE, otherwise, set to
- * FALSE. When TRUE, we use an ANSI keyboard
- * instead of the actual keyboard.
- */
- void InitByLayoutID(SInt32 aLayoutID, bool aOverrideKeyboard = false);
- void InitByCurrentInputSource();
- void InitByCurrentKeyboardLayout();
- void InitByCurrentASCIICapableInputSource();
- void InitByCurrentASCIICapableKeyboardLayout();
- void InitByCurrentInputMethodKeyboardLayoutOverride();
- void InitByTISInputSourceRef(TISInputSourceRef aInputSource);
- void InitByLanguage(CFStringRef aLanguage);
-
- /**
- * If the instance is initialized with a keyboard layout input source,
- * returns it.
- * If the instance is initialized with an IME mode input source, the result
- * references the keyboard layout for the IME mode. However, this can be
- * initialized only when the IME mode is actually selected. I.e, if IME mode
- * input source is initialized with LayoutID or SourceID, this returns null.
- */
- TISInputSourceRef GetKeyboardLayoutInputSource() const
- {
- return mKeyboardLayout;
- }
- const UCKeyboardLayout* GetUCKeyboardLayout();
-
- bool IsOpenedIMEMode();
- bool IsIMEMode();
- bool IsKeyboardLayout();
-
- bool IsASCIICapable()
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetBoolProperty(kTISPropertyInputSourceIsASCIICapable);
- }
-
- bool IsEnabled()
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetBoolProperty(kTISPropertyInputSourceIsEnabled);
- }
-
- bool GetLanguageList(CFArrayRef &aLanguageList);
- bool GetPrimaryLanguage(CFStringRef &aPrimaryLanguage);
- bool GetPrimaryLanguage(nsAString &aPrimaryLanguage);
-
- bool GetLocalizedName(CFStringRef &aName)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyLocalizedName, aName);
- }
-
- bool GetLocalizedName(nsAString &aName)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyLocalizedName, aName);
- }
-
- bool GetInputSourceID(CFStringRef &aID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceID, aID);
- }
-
- bool GetInputSourceID(nsAString &aID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceID, aID);
- }
-
- bool GetBundleID(CFStringRef &aBundleID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyBundleID, aBundleID);
- }
-
- bool GetBundleID(nsAString &aBundleID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyBundleID, aBundleID);
- }
-
- bool GetInputSourceType(CFStringRef &aType)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceType, aType);
- }
-
- bool GetInputSourceType(nsAString &aType)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceType, aType);
- }
-
- bool IsForRTLLanguage();
- bool IsInitializedByCurrentInputSource();
-
- enum {
- // 40 is an actual result of the ::LMGetKbdType() when we connect an
- // unknown keyboard and set the keyboard type to ANSI manually on the
- // set up dialog.
- eKbdType_ANSI = 40
- };
-
- void Select();
- void Clear();
-
- /**
- * InitKeyEvent() initializes aKeyEvent for aNativeKeyEvent.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- */
- void InitKeyEvent(NSEvent *aNativeKeyEvent, WidgetKeyboardEvent& aKeyEvent,
- const nsAString *aInsertString = nullptr);
-
- /**
- * WillDispatchKeyboardEvent() computes aKeyEvent.mAlternativeCharCodes and
- * recompute aKeyEvent.mCharCode if it's necessary.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event. This must be
- * eKeyPress event.
- */
- void WillDispatchKeyboardEvent(NSEvent* aNativeKeyEvent,
- const nsAString* aInsertString,
- WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * ComputeGeckoKeyCode() returns Gecko keycode for aNativeKeyCode on current
- * keyboard layout.
- *
- * @param aNativeKeyCode A native keycode.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @param aCmdIsPressed TRUE if Cmd key is pressed. Otherwise, FALSE.
- * @return The computed Gecko keycode.
- */
- uint32_t ComputeGeckoKeyCode(UInt32 aNativeKeyCode, UInt32 aKbType,
- bool aCmdIsPressed);
-
- /**
- * ComputeGeckoKeyNameIndex() returns Gecko key name index for the key.
- *
- * @param aNativeKeyCode A native keycode.
- */
- static KeyNameIndex ComputeGeckoKeyNameIndex(UInt32 aNativeKeyCode);
-
- /**
- * ComputeGeckoCodeNameIndex() returns Gecko code name index for the key.
- *
- * @param aNativeKeyCode A native keycode.
- */
- static CodeNameIndex ComputeGeckoCodeNameIndex(UInt32 aNativeKeyCode);
-
-protected:
- /**
- * TranslateToString() computes the inputted text from the native keyCode,
- * modifier flags and keyboard type.
- *
- * @param aKeyCode A native keyCode.
- * @param aModifiers Combination of native modifier flags.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @param aStr Result, i.e., inputted text.
- * The result can be two or more characters.
- * @return If succeeded, TRUE. Otherwise, FALSE.
- * Even if TRUE, aStr can be empty string.
- */
- bool TranslateToString(UInt32 aKeyCode, UInt32 aModifiers,
- UInt32 aKbType, nsAString &aStr);
-
- /**
- * TranslateToChar() computes the inputted character from the native keyCode,
- * modifier flags and keyboard type. If two or more characters would be
- * input, this returns 0.
- *
- * @param aKeyCode A native keyCode.
- * @param aModifiers Combination of native modifier flags.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @return If succeeded and the result is one character,
- * returns the charCode of it. Otherwise,
- * returns 0.
- */
- uint32_t TranslateToChar(UInt32 aKeyCode, UInt32 aModifiers, UInt32 aKbType);
-
- /**
- * ComputeInsertString() computes string to be inserted with the key event.
- *
- * @param aNativeKeyEvent The native key event which causes our keyboard
- * event(s).
- * @param aKeyEvent A Gecko key event which was partially
- * initialized with aNativeKeyEvent.
- * @param aInsertString The string to be inputting by aNativeKeyEvent.
- * This should be specified by InsertText().
- * In other words, if the key event doesn't cause
- * a call of InsertText(), this can be nullptr.
- * @param aResult The string which should be set to charCode of
- * keypress event(s).
- */
- void ComputeInsertStringForCharCode(NSEvent* aNativeKeyEvent,
- const WidgetKeyboardEvent& aKeyEvent,
- const nsAString* aInsertString,
- nsAString& aResult);
-
- /**
- * IsPrintableKeyEvent() returns true if aNativeKeyEvent is caused by
- * a printable key. Otherwise, returns false.
- */
- bool IsPrintableKeyEvent(NSEvent* aNativeKeyEvent) const;
-
- /**
- * GetKbdType() returns physical keyboard type.
- */
- UInt32 GetKbdType() const;
-
- bool GetBoolProperty(const CFStringRef aKey);
- bool GetStringProperty(const CFStringRef aKey, CFStringRef &aStr);
- bool GetStringProperty(const CFStringRef aKey, nsAString &aStr);
-
- TISInputSourceRef mInputSource;
- TISInputSourceRef mKeyboardLayout;
- CFArrayRef mInputSourceList;
- const UCKeyboardLayout* mUCKeyboardLayout;
- int8_t mIsRTL;
-
- bool mOverrideKeyboard;
-
- static TISInputSourceWrapper* sCurrentInputSource;
-};
-
-/**
- * TextInputHandlerBase is a base class of IMEInputHandler and TextInputHandler.
- * Utility methods should be implemented this level.
- */
-
-class TextInputHandlerBase : public TextEventDispatcherListener
-{
-public:
- /**
- * Other TextEventDispatcherListener methods should be implemented in
- * IMEInputHandler.
- */
- NS_DECL_ISUPPORTS
-
- /**
- * DispatchEvent() dispatches aEvent on mWidget.
- *
- * @param aEvent An event which you want to dispatch.
- * @return TRUE if the event is consumed by web contents
- * or chrome contents. Otherwise, FALSE.
- */
- bool DispatchEvent(WidgetGUIEvent& aEvent);
-
- /**
- * SetSelection() dispatches eSetSelection event for the aRange.
- *
- * @param aRange The range which will be selected.
- * @return TRUE if setting selection is succeeded and
- * the widget hasn't been destroyed.
- * Otherwise, FALSE.
- */
- bool SetSelection(NSRange& aRange);
-
- /**
- * InitKeyEvent() initializes aKeyEvent for aNativeKeyEvent.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- */
- void InitKeyEvent(NSEvent *aNativeKeyEvent, WidgetKeyboardEvent& aKeyEvent,
- const nsAString *aInsertString = nullptr);
-
- /**
- * SynthesizeNativeKeyEvent() is an implementation of
- * nsIWidget::SynthesizeNativeKeyEvent(). See the document in nsIWidget.h
- * for the detail.
- */
- nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
- int32_t aNativeKeyCode,
- uint32_t aModifierFlags,
- const nsAString& aCharacters,
- const nsAString& aUnmodifiedCharacters);
-
- /**
- * Utility method intended for testing. Attempts to construct a native key
- * event that would have been generated during an actual key press. This
- * *does not dispatch* the native event. Instead, it is attached to the
- * |mNativeKeyEvent| field of the Gecko event that is passed in.
- * @param aKeyEvent Gecko key event to attach the native event to
- */
- NS_IMETHOD AttachNativeKeyEvent(WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * GetWindowLevel() returns the window level of current focused (in Gecko)
- * window. E.g., if an <input> element in XUL panel has focus, this returns
- * the XUL panel's window level.
- */
- NSInteger GetWindowLevel();
-
- /**
- * IsSpecialGeckoKey() checks whether aNativeKeyCode is mapped to a special
- * Gecko keyCode. A key is "special" if it isn't used for text input.
- *
- * @param aNativeKeyCode A native keycode.
- * @return If the keycode is mapped to a special key,
- * TRUE. Otherwise, FALSE.
- */
- static bool IsSpecialGeckoKey(UInt32 aNativeKeyCode);
-
-
- /**
- * EnableSecureEventInput() and DisableSecureEventInput() wrap the Carbon
- * Event Manager APIs with the same names. In addition they keep track of
- * how many times we've called them (in the same process) -- unlike the
- * Carbon Event Manager APIs, which only keep track of how many times they've
- * been called from any and all processes.
- *
- * The Carbon Event Manager's IsSecureEventInputEnabled() returns whether
- * secure event input mode is enabled (in any process). This class's
- * IsSecureEventInputEnabled() returns whether we've made any calls to
- * EnableSecureEventInput() that are not (yet) offset by the calls we've
- * made to DisableSecureEventInput().
- */
- static void EnableSecureEventInput();
- static void DisableSecureEventInput();
- static bool IsSecureEventInputEnabled();
-
- /**
- * EnsureSecureEventInputDisabled() calls DisableSecureEventInput() until
- * our call count becomes 0.
- */
- static void EnsureSecureEventInputDisabled();
-
-public:
- /**
- * mWidget must not be destroyed without OnDestroyWidget being called.
- *
- * @param aDestroyingWidget Destroying widget. This might not be mWidget.
- * @return This result doesn't have any meaning for
- * callers. When aDstroyingWidget isn't the same
- * as mWidget, FALSE. Then, inherited methods in
- * sub classes should return from this method
- * without cleaning up.
- */
- virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget);
-
-protected:
- // The creator of this instance, client and its text event dispatcher.
- // These members must not be nullptr after initialized until
- // OnDestroyWidget() is called.
- nsChildView* mWidget; // [WEAK]
- RefPtr<TextEventDispatcher> mDispatcher;
-
- // The native view for mWidget.
- // This view handles the actual text inputting.
- NSView<mozView>* mView; // [STRONG]
-
- TextInputHandlerBase(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~TextInputHandlerBase();
-
- bool Destroyed() { return !mWidget; }
-
- /**
- * mCurrentKeyEvent indicates what key event we are handling. While
- * handling a native keydown event, we need to store the event for insertText,
- * doCommandBySelector and various action message handlers of NSResponder
- * such as [NSResponder insertNewline:sender].
- */
- struct KeyEventState
- {
- // Handling native key event
- NSEvent* mKeyEvent;
- // String specified by InsertText(). This is not null only during a
- // call of InsertText().
- nsAString* mInsertString;
- // String which are included in [mKeyEvent characters] and already handled
- // by InsertText() call(s).
- nsString mInsertedString;
- // Whether keydown event was consumed by web contents or chrome contents.
- bool mKeyDownHandled;
- // Whether keypress event was dispatched for mKeyEvent.
- bool mKeyPressDispatched;
- // Whether keypress event was consumed by web contents or chrome contents.
- bool mKeyPressHandled;
- // Whether the key event causes other key events via IME or something.
- bool mCausedOtherKeyEvents;
- // Whether the key event causes composition change or committing
- // composition. So, even if InsertText() is called, this may be false
- // if it dispatches keypress event.
- bool mCompositionDispatched;
-
- KeyEventState() : mKeyEvent(nullptr)
- {
- Clear();
- }
-
- explicit KeyEventState(NSEvent* aNativeKeyEvent) : mKeyEvent(nullptr)
- {
- Clear();
- Set(aNativeKeyEvent);
- }
-
- KeyEventState(const KeyEventState &aOther) = delete;
-
- ~KeyEventState()
- {
- Clear();
- }
-
- void Set(NSEvent* aNativeKeyEvent)
- {
- NS_PRECONDITION(aNativeKeyEvent, "aNativeKeyEvent must not be NULL");
- Clear();
- mKeyEvent = [aNativeKeyEvent retain];
- }
-
- void Clear()
- {
- if (mKeyEvent) {
- [mKeyEvent release];
- mKeyEvent = nullptr;
- }
- mInsertString = nullptr;
- mInsertedString.Truncate();
- mKeyDownHandled = false;
- mKeyPressDispatched = false;
- mKeyPressHandled = false;
- mCausedOtherKeyEvents = false;
- mCompositionDispatched = false;
- }
-
- bool IsDefaultPrevented() const
- {
- return mKeyDownHandled || mKeyPressHandled || mCausedOtherKeyEvents ||
- mCompositionDispatched;
- }
-
- bool CanDispatchKeyPressEvent() const
- {
- return !mKeyPressDispatched && !IsDefaultPrevented();
- }
-
- void InitKeyEvent(TextInputHandlerBase* aHandler,
- WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * GetUnhandledString() returns characters of the event which have not been
- * handled with InsertText() yet. For example, if there is a composition
- * caused by a dead key press like '`' and it's committed by some key
- * combinations like |Cmd+v|, then, the |v|'s KeyDown event's |characters|
- * is |`v|. Then, after |`| is committed with a call of InsertString(),
- * this returns only 'v'.
- */
- void GetUnhandledString(nsAString& aUnhandledString) const;
- };
-
- /**
- * Helper classes for guaranteeing cleaning mCurrentKeyEvent
- */
- class AutoKeyEventStateCleaner
- {
- public:
- explicit AutoKeyEventStateCleaner(TextInputHandlerBase* aHandler) :
- mHandler(aHandler)
- {
- }
-
- ~AutoKeyEventStateCleaner()
- {
- mHandler->RemoveCurrentKeyEvent();
- }
- private:
- RefPtr<TextInputHandlerBase> mHandler;
- };
-
- class MOZ_STACK_CLASS AutoInsertStringClearer
- {
- public:
- explicit AutoInsertStringClearer(KeyEventState* aState)
- : mState(aState)
- {
- }
- ~AutoInsertStringClearer();
-
- private:
- KeyEventState* mState;
- };
-
- /**
- * mCurrentKeyEvents stores all key events which are being processed.
- * When we call interpretKeyEvents, IME may generate other key events.
- * mCurrentKeyEvents[0] is the latest key event.
- */
- nsTArray<KeyEventState*> mCurrentKeyEvents;
-
- /**
- * mFirstKeyEvent must be used for first key event. This member prevents
- * memory fragmentation for most key events.
- */
- KeyEventState mFirstKeyEvent;
-
- /**
- * PushKeyEvent() adds the current key event to mCurrentKeyEvents.
- */
- KeyEventState* PushKeyEvent(NSEvent* aNativeKeyEvent)
- {
- uint32_t nestCount = mCurrentKeyEvents.Length();
- for (uint32_t i = 0; i < nestCount; i++) {
- // When the key event is caused by another key event, all key events
- // which are being handled should be marked as "consumed".
- mCurrentKeyEvents[i]->mCausedOtherKeyEvents = true;
- }
-
- KeyEventState* keyEvent = nullptr;
- if (nestCount == 0) {
- mFirstKeyEvent.Set(aNativeKeyEvent);
- keyEvent = &mFirstKeyEvent;
- } else {
- keyEvent = new KeyEventState(aNativeKeyEvent);
- }
- return *mCurrentKeyEvents.AppendElement(keyEvent);
- }
-
- /**
- * RemoveCurrentKeyEvent() removes the current key event from
- * mCurrentKeyEvents.
- */
- void RemoveCurrentKeyEvent()
- {
- NS_ASSERTION(mCurrentKeyEvents.Length() > 0,
- "RemoveCurrentKeyEvent() is called unexpectedly");
- KeyEventState* keyEvent = GetCurrentKeyEvent();
- mCurrentKeyEvents.RemoveElementAt(mCurrentKeyEvents.Length() - 1);
- if (keyEvent == &mFirstKeyEvent) {
- keyEvent->Clear();
- } else {
- delete keyEvent;
- }
- }
-
- /**
- * GetCurrentKeyEvent() returns current processing key event.
- */
- KeyEventState* GetCurrentKeyEvent()
- {
- if (mCurrentKeyEvents.Length() == 0) {
- return nullptr;
- }
- return mCurrentKeyEvents[mCurrentKeyEvents.Length() - 1];
- }
-
- struct KeyboardLayoutOverride final
- {
- int32_t mKeyboardLayout;
- bool mOverrideEnabled;
-
- KeyboardLayoutOverride() :
- mKeyboardLayout(0), mOverrideEnabled(false)
- {
- }
- };
-
- const KeyboardLayoutOverride& KeyboardLayoutOverrideRef() const
- {
- return mKeyboardOverride;
- }
-
- /**
- * IsPrintableChar() checks whether the unicode character is
- * a non-printable ASCII character or not. Note that this returns
- * TRUE even if aChar is a non-printable UNICODE character.
- *
- * @param aChar A unicode character.
- * @return TRUE if aChar is a printable ASCII character
- * or a unicode character. Otherwise, i.e,
- * if aChar is a non-printable ASCII character,
- * FALSE.
- */
- static bool IsPrintableChar(char16_t aChar);
-
- /**
- * IsNormalCharInputtingEvent() checks whether aKeyEvent causes text input.
- *
- * @param aKeyEvent A key event.
- * @return TRUE if the key event causes text input.
- * Otherwise, FALSE.
- */
- static bool IsNormalCharInputtingEvent(const WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * IsModifierKey() checks whether the native keyCode is for a modifier key.
- *
- * @param aNativeKeyCode A native keyCode.
- * @return TRUE if aNativeKeyCode is for a modifier key.
- * Otherwise, FALSE.
- */
- static bool IsModifierKey(UInt32 aNativeKeyCode);
-
-private:
- KeyboardLayoutOverride mKeyboardOverride;
-
- static int32_t sSecureEventInputCount;
-};
-
-/**
- * IMEInputHandler manages:
- * 1. The IME/keyboard layout statement of nsChildView.
- * 2. The IME composition statement of nsChildView.
- * And also provides the methods which controls the current IME transaction of
- * the instance.
- *
- * Note that an nsChildView handles one or more NSView's events. E.g., even if
- * a text editor on XUL panel element, the input events handled on the parent
- * (or its ancestor) widget handles it (the native focus is set to it). The
- * actual focused view is notified by OnFocusChangeInGecko.
- */
-
-class IMEInputHandler : public TextInputHandlerBase
-{
-public:
- // TextEventDispatcherListener methods
- NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
- const IMENotification& aNotification) override;
- NS_IMETHOD_(void) OnRemovedFrom(
- TextEventDispatcher* aTextEventDispatcher) override;
- NS_IMETHOD_(void) WillDispatchKeyboardEvent(
- TextEventDispatcher* aTextEventDispatcher,
- WidgetKeyboardEvent& aKeyboardEvent,
- uint32_t aIndexOfKeypress,
- void* aData) override;
-
-public:
- virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget) override;
-
- virtual void OnFocusChangeInGecko(bool aFocus);
-
- void OnSelectionChange(const IMENotification& aIMENotification);
-
- /**
- * Call [NSTextInputContext handleEvent] for mouse event support of IME
- */
- bool OnHandleEvent(NSEvent* aEvent);
-
- /**
- * SetMarkedText() is a handler of setMarkedText of NSTextInput.
- *
- * @param aAttrString This mut be an instance of NSAttributedString.
- * If the aString parameter to
- * [ChildView setMarkedText:setSelectedRange:]
- * isn't an instance of NSAttributedString,
- * create an NSAttributedString from it and pass
- * that instead.
- * @param aSelectedRange Current selected range (or caret position).
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current marked range.
- */
- void SetMarkedText(NSAttributedString* aAttrString,
- NSRange& aSelectedRange,
- NSRange* aReplacementRange = nullptr);
-
- /**
- * GetAttributedSubstringFromRange() returns an NSAttributedString instance
- * which is allocated as autorelease for aRange.
- *
- * @param aRange The range of string which you want.
- * @param aActualRange The actual range of the result.
- * @return The string in aRange. If the string is empty,
- * this returns nil. If succeeded, this returns
- * an instance which is allocated as autorelease.
- * If this has some troubles, returns nil.
- */
- NSAttributedString* GetAttributedSubstringFromRange(
- NSRange& aRange,
- NSRange* aActualRange = nullptr);
-
- /**
- * SelectedRange() returns current selected range.
- *
- * @return If an editor has focus, this returns selection
- * range in the editor. Otherwise, this returns
- * selection range in the focused document.
- */
- NSRange SelectedRange();
-
- /**
- * DrawsVerticallyForCharacterAtIndex() returns whether the character at
- * the given index is being rendered vertically.
- *
- * @param aCharIndex The character offset to query.
- *
- * @return True if writing-mode is vertical at the given
- * character offset; otherwise false.
- */
- bool DrawsVerticallyForCharacterAtIndex(uint32_t aCharIndex);
-
- /**
- * FirstRectForCharacterRange() returns first *character* rect in the range.
- * Cocoa needs the first line rect in the range, but we cannot compute it
- * on current implementation.
- *
- * @param aRange A range of text to examine. Its position is
- * an offset from the beginning of the focused
- * editor or document.
- * @param aActualRange If this is not null, this returns the actual
- * range used for computing the result.
- * @return An NSRect containing the first character in
- * aRange, in screen coordinates.
- * If the length of aRange is 0, the width will
- * be 0.
- */
- NSRect FirstRectForCharacterRange(NSRange& aRange,
- NSRange* aActualRange = nullptr);
-
- /**
- * CharacterIndexForPoint() returns an offset of a character at aPoint.
- * XXX This isn't implemented, always returns 0.
- *
- * @param The point in screen coordinates.
- * @return The offset of the character at aPoint from
- * the beginning of the focused editor or
- * document.
- */
- NSUInteger CharacterIndexForPoint(NSPoint& aPoint);
-
- /**
- * GetValidAttributesForMarkedText() returns attributes which we support.
- *
- * @return Always empty array for now.
- */
- NSArray* GetValidAttributesForMarkedText();
-
- bool HasMarkedText();
- NSRange MarkedRange();
-
- bool IsIMEComposing() { return mIsIMEComposing; }
- bool IsIMEOpened();
- bool IsIMEEnabled() { return mIsIMEEnabled; }
- bool IsASCIICapableOnly() { return mIsASCIICapableOnly; }
- bool IgnoreIMECommit() { return mIgnoreIMECommit; }
-
- bool IgnoreIMEComposition()
- {
- // Ignore the IME composition events when we're pending to discard the
- // composition and we are not to handle the IME composition now.
- return (mPendingMethods & kDiscardIMEComposition) &&
- (mIsInFocusProcessing || !IsFocused());
- }
-
- void CommitIMEComposition();
- void CancelIMEComposition();
-
- void EnableIME(bool aEnableIME);
- void SetIMEOpenState(bool aOpen);
- void SetASCIICapableOnly(bool aASCIICapableOnly);
-
- /**
- * True if OSX believes that our view has keyboard focus.
- */
- bool IsFocused();
-
- static CFArrayRef CreateAllIMEModeList();
- static void DebugPrintAllIMEModes();
-
- // Don't use ::TSMGetActiveDocument() API directly, the document may not
- // be what you want.
- static TSMDocumentID GetCurrentTSMDocumentID();
-
-protected:
- // We cannot do some jobs in the given stack by some reasons.
- // Following flags and the timer provide the execution pending mechanism,
- // See the comment in nsCocoaTextInputHandler.mm.
- nsCOMPtr<nsITimer> mTimer;
- enum {
- kNotifyIMEOfFocusChangeInGecko = 1,
- kDiscardIMEComposition = 2,
- kSyncASCIICapableOnly = 4
- };
- uint32_t mPendingMethods;
-
- IMEInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~IMEInputHandler();
-
- void ResetTimer();
-
- virtual void ExecutePendingMethods();
-
- /**
- * InsertTextAsCommittingComposition() commits current composition. If there
- * is no composition, this starts a composition and commits it immediately.
- *
- * @param aAttrString A string which is committed.
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current selection.
- */
- void InsertTextAsCommittingComposition(NSAttributedString* aAttrString,
- NSRange* aReplacementRange);
-
-private:
- // If mIsIMEComposing is true, the composition string is stored here.
- NSString* mIMECompositionString;
- // If mIsIMEComposing is true, the start offset of the composition string.
- uint32_t mIMECompositionStart;
-
- NSRange mMarkedRange;
- NSRange mSelectedRange;
-
- NSRange mRangeForWritingMode; // range within which mWritingMode applies
- mozilla::WritingMode mWritingMode;
-
- bool mIsIMEComposing;
- bool mIsIMEEnabled;
- bool mIsASCIICapableOnly;
- bool mIgnoreIMECommit;
- // This flag is enabled by OnFocusChangeInGecko, and will be cleared by
- // ExecutePendingMethods. When this is true, IsFocus() returns TRUE. At
- // that time, the focus processing in Gecko might not be finished yet. So,
- // you cannot use WidgetQueryContentEvent or something.
- bool mIsInFocusProcessing;
- bool mIMEHasFocus;
-
- void KillIMEComposition();
- void SendCommittedText(NSString *aString);
- void OpenSystemPreferredLanguageIME();
-
- // Pending methods
- void NotifyIMEOfFocusChangeInGecko();
- void DiscardIMEComposition();
- void SyncASCIICapableOnly();
-
- static bool sStaticMembersInitialized;
- static CFStringRef sLatestIMEOpenedModeInputSourceID;
- static void InitStaticMembers();
- static void OnCurrentTextInputSourceChange(CFNotificationCenterRef aCenter,
- void* aObserver,
- CFStringRef aName,
- const void* aObject,
- CFDictionaryRef aUserInfo);
-
- static void FlushPendingMethods(nsITimer* aTimer, void* aClosure);
-
- /**
- * ConvertToTextRangeStyle converts the given native underline style to
- * our defined text range type.
- *
- * @param aUnderlineStyle NSUnderlineStyleSingle or
- * NSUnderlineStyleThick.
- * @param aSelectedRange Current selected range (or caret position).
- * @return NS_TEXTRANGE_*.
- */
- TextRangeType ConvertToTextRangeType(uint32_t aUnderlineStyle,
- NSRange& aSelectedRange);
-
- /**
- * GetRangeCount() computes the range count of aAttrString.
- *
- * @param aAttrString An NSAttributedString instance whose number of
- * NSUnderlineStyleAttributeName ranges you with
- * to know.
- * @return The count of NSUnderlineStyleAttributeName
- * ranges in aAttrString.
- */
- uint32_t GetRangeCount(NSAttributedString *aString);
-
- /**
- * CreateTextRangeArray() returns text ranges for clauses and/or caret.
- *
- * @param aAttrString An NSAttributedString instance which indicates
- * current composition string.
- * @param aSelectedRange Current selected range (or caret position).
- * @return The result is set to the
- * NSUnderlineStyleAttributeName ranges in
- * aAttrString.
- */
- already_AddRefed<mozilla::TextRangeArray>
- CreateTextRangeArray(NSAttributedString *aAttrString,
- NSRange& aSelectedRange);
-
- /**
- * DispatchCompositionStartEvent() dispatches a compositionstart event and
- * initializes the members indicating composition state.
- *
- * @return true if it can continues handling composition.
- * Otherwise, e.g., canceled by the web page,
- * this returns false.
- */
- bool DispatchCompositionStartEvent();
-
- /**
- * DispatchCompositionChangeEvent() dispatches a compositionchange event on
- * mWidget and modifies the members indicating composition state.
- *
- * @param aText User text input.
- * @param aAttrString An NSAttributedString instance which indicates
- * current composition string.
- * @param aSelectedRange Current selected range (or caret position).
- *
- * @return true if it can continues handling composition.
- * Otherwise, e.g., canceled by the web page,
- * this returns false.
- */
- bool DispatchCompositionChangeEvent(const nsString& aText,
- NSAttributedString* aAttrString,
- NSRange& aSelectedRange);
-
- /**
- * DispatchCompositionCommitEvent() dispatches a compositioncommit event or
- * compositioncommitasis event. If aCommitString is null, dispatches
- * compositioncommitasis event. I.e., if aCommitString is null, this
- * commits the composition with the last data. Otherwise, commits the
- * composition with aCommitString value.
- *
- * @return true if the widget isn't destroyed.
- * Otherwise, false.
- */
- bool DispatchCompositionCommitEvent(const nsAString* aCommitString = nullptr);
-
- // The focused IME handler. Please note that the handler might lost the
- // actual focus by deactivating the application. If we are active, this
- // must have the actual focused handle.
- // We cannot access to the NSInputManager during we aren't active, so, the
- // focused handler can have an IME transaction even if we are deactive.
- static IMEInputHandler* sFocusedIMEHandler;
-
- static bool sCachedIsForRTLLangage;
-};
-
-/**
- * TextInputHandler implements the NSTextInput protocol.
- */
-class TextInputHandler : public IMEInputHandler
-{
-public:
- static NSUInteger sLastModifierState;
-
- static CFArrayRef CreateAllKeyboardLayoutList();
- static void DebugPrintAllKeyboardLayouts();
-
- TextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~TextInputHandler();
-
- /**
- * KeyDown event handler.
- *
- * @param aNativeEvent A native NSKeyDown event.
- * @return TRUE if the event is consumed by web contents
- * or chrome contents. Otherwise, FALSE.
- */
- bool HandleKeyDownEvent(NSEvent* aNativeEvent);
-
- /**
- * KeyUp event handler.
- *
- * @param aNativeEvent A native NSKeyUp event.
- */
- void HandleKeyUpEvent(NSEvent* aNativeEvent);
-
- /**
- * FlagsChanged event handler.
- *
- * @param aNativeEvent A native NSFlagsChanged event.
- */
- void HandleFlagsChanged(NSEvent* aNativeEvent);
-
- /**
- * Insert the string to content. I.e., this is a text input event handler.
- * If this is called during keydown event handling, this may dispatch a
- * eKeyPress event. If this is called during composition, this commits
- * the composition by the aAttrString.
- *
- * @param aAttrString An inserted string.
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current selection.
- */
- void InsertText(NSAttributedString *aAttrString,
- NSRange* aReplacementRange = nullptr);
-
- /**
- * doCommandBySelector event handler.
- *
- * @param aSelector A selector of the command.
- * @return TRUE if the command is consumed. Otherwise,
- * FALSE.
- */
- bool DoCommandBySelector(const char* aSelector);
-
- /**
- * KeyPressWasHandled() checks whether keypress event was handled or not.
- *
- * @return TRUE if keypress event for latest native key
- * event was handled. Otherwise, FALSE.
- * If this handler isn't handling any key events,
- * always returns FALSE.
- */
- bool KeyPressWasHandled()
- {
- KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
- return currentKeyEvent && currentKeyEvent->mKeyPressHandled;
- }
-
-protected:
- // Stores the association of device dependent modifier flags with a modifier
- // keyCode. Being device dependent, this association may differ from one kind
- // of hardware to the next.
- struct ModifierKey
- {
- NSUInteger flags;
- unsigned short keyCode;
-
- ModifierKey(NSUInteger aFlags, unsigned short aKeyCode) :
- flags(aFlags), keyCode(aKeyCode)
- {
- }
-
- NSUInteger GetDeviceDependentFlags() const
- {
- return (flags & ~NSDeviceIndependentModifierFlagsMask);
- }
-
- NSUInteger GetDeviceIndependentFlags() const
- {
- return (flags & NSDeviceIndependentModifierFlagsMask);
- }
- };
- typedef nsTArray<ModifierKey> ModifierKeyArray;
- ModifierKeyArray mModifierKeys;
-
- /**
- * GetModifierKeyForNativeKeyCode() returns the stored ModifierKey for
- * the key.
- */
- const ModifierKey*
- GetModifierKeyForNativeKeyCode(unsigned short aKeyCode) const;
-
- /**
- * GetModifierKeyForDeviceDependentFlags() returns the stored ModifierKey for
- * the device dependent flags.
- */
- const ModifierKey*
- GetModifierKeyForDeviceDependentFlags(NSUInteger aFlags) const;
-
- /**
- * DispatchKeyEventForFlagsChanged() dispatches keydown event or keyup event
- * for the aNativeEvent.
- *
- * @param aNativeEvent A native flagschanged event which you want to
- * dispatch our key event for.
- * @param aDispatchKeyDown TRUE if you want to dispatch a keydown event.
- * Otherwise, i.e., to dispatch keyup event,
- * FALSE.
- */
- void DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
- bool aDispatchKeyDown);
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif // TextInputHandler_h_