widget/gtk/nsGtkIMModule.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim:expandtab:shiftwidth=4:tabstop=4:
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #ifndef __nsGtkIMModule_h__
     9 #define __nsGtkIMModule_h__
    11 #include <gdk/gdk.h>
    12 #include <gtk/gtk.h>
    14 #include "nsString.h"
    15 #include "nsAutoPtr.h"
    16 #include "nsCOMPtr.h"
    17 #include "nsTArray.h"
    18 #include "nsIWidget.h"
    19 #include "mozilla/EventForwards.h"
    21 class nsWindow;
    23 class nsGtkIMModule
    24 {
    25 protected:
    26     typedef mozilla::widget::InputContext InputContext;
    27     typedef mozilla::widget::InputContextAction InputContextAction;
    29 public:
    30     nsrefcnt AddRef()
    31     {
    32         NS_PRECONDITION(int32_t(mRefCnt) >= 0, "mRefCnt is negative");
    33         ++mRefCnt;
    34         NS_LOG_ADDREF(this, mRefCnt, "nsGtkIMModule", sizeof(*this));
    35         return mRefCnt;
    36     }
    37     nsrefcnt Release()
    38     {
    39         NS_PRECONDITION(mRefCnt != 0, "mRefCnt is alrady zero");
    40         --mRefCnt;
    41         NS_LOG_RELEASE(this, mRefCnt, "nsGtkIMModule");
    42         if (mRefCnt == 0) {
    43             mRefCnt = 1; /* stabilize */
    44             delete this;
    45             return 0;
    46         }
    47         return mRefCnt;
    48     }
    50 protected:
    51     nsAutoRefCnt mRefCnt;
    53 public:
    54     // aOwnerWindow is a pointer of the owner window.  When aOwnerWindow is
    55     // destroyed, the related IME contexts are released (i.e., IME cannot be
    56     // used with the instance after that).
    57     nsGtkIMModule(nsWindow* aOwnerWindow);
    58     ~nsGtkIMModule();
    60     // "Enabled" means the users can use all IMEs.
    61     // I.e., the focus is in the normal editors.
    62     bool IsEnabled();
    64     // OnFocusWindow is a notification that aWindow is going to be focused.
    65     void OnFocusWindow(nsWindow* aWindow);
    66     // OnBlurWindow is a notification that aWindow is going to be unfocused.
    67     void OnBlurWindow(nsWindow* aWindow);
    68     // OnDestroyWindow is a notification that aWindow is going to be destroyed.
    69     void OnDestroyWindow(nsWindow* aWindow);
    70     // OnFocusChangeInGecko is a notification that an editor gets focus.
    71     void OnFocusChangeInGecko(bool aFocus);
    73     // OnKeyEvent is called when aWindow gets a native key press event or a
    74     // native key release event.  If this returns TRUE, the key event was
    75     // filtered by IME.  Otherwise, this returns FALSE.
    76     // NOTE: When the keypress event starts composition, this returns TRUE but
    77     //       this dispatches keydown event before compositionstart event.
    78     bool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent,
    79                       bool aKeyDownEventWasSent = false);
    81     // IME related nsIWidget methods.
    82     nsresult CommitIMEComposition(nsWindow* aCaller);
    83     void SetInputContext(nsWindow* aCaller,
    84                          const InputContext* aContext,
    85                          const InputContextAction* aAction);
    86     InputContext GetInputContext();
    87     nsresult CancelIMEComposition(nsWindow* aCaller);
    88     void OnUpdateComposition();
    90     // If a software keyboard has been opened, this returns TRUE.
    91     // Otherwise, FALSE.
    92     static bool IsVirtualKeyboardOpened();
    94 protected:
    95     // Owner of an instance of this class. This should be top level window.
    96     // The owner window must release the contexts when it's destroyed because
    97     // the IME contexts need the native window.  If OnDestroyWindow() is called
    98     // with the owner window, it'll release IME contexts.  Otherwise, it'll
    99     // just clean up any existing composition if it's related to the destroying
   100     // child window.
   101     nsWindow* mOwnerWindow;
   103     // A last focused window in this class's context.
   104     nsWindow* mLastFocusedWindow;
   106     // Actual context. This is used for handling the user's input.
   107     GtkIMContext       *mContext;
   109     // mSimpleContext is used for the password field and
   110     // the |ime-mode: disabled;| editors if sUseSimpleContext is true.
   111     // These editors disable IME.  But dead keys should work.  Fortunately,
   112     // the simple IM context of GTK2 support only them.
   113     GtkIMContext       *mSimpleContext;
   115     // mDummyContext is a dummy context and will be used in Focus()
   116     // when the state of mEnabled means disabled.  This context's IME state is
   117     // always "closed", so it closes IME forcedly.
   118     GtkIMContext       *mDummyContext;
   120     // IME enabled state and other things defined in InputContext.
   121     // Use following helper methods if you don't need the detail of the status.
   122     InputContext mInputContext;
   124     // mCompositionStart is the start offset of the composition string in the
   125     // current content.  When <textarea> or <input> have focus, it means offset
   126     // from the first character of them.  When a HTML editor has focus, it
   127     // means offset from the first character of the root element of the editor.
   128     uint32_t mCompositionStart;
   130     // mDispatchedCompositionString is the latest composition string which
   131     // was dispatched by compositionupdate event.
   132     nsString mDispatchedCompositionString;
   134     // mSelectedString is the selected string which was removed by first
   135     // text event.
   136     nsString mSelectedString;
   138     // OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
   139     // event.
   140     GdkEventKey* mProcessingKeyEvent;
   142     // current target offset of IME composition
   143     uint32_t mCompositionTargetOffset;
   145     // mCompositionState indicates current status of composition.
   146     enum eCompositionState {
   147         eCompositionState_NotComposing,
   148         eCompositionState_CompositionStartDispatched,
   149         eCompositionState_TextEventDispatched,
   150         eCompositionState_CommitTextEventDispatched
   151     };
   152     eCompositionState mCompositionState;
   154     bool IsComposing()
   155     {
   156         return (mCompositionState != eCompositionState_NotComposing);
   157     }
   159     bool EditorHasCompositionString()
   160     {
   161         return (mCompositionState == eCompositionState_TextEventDispatched);
   162     }
   164 #ifdef PR_LOGGING
   165     const char* GetCompositionStateName()
   166     {
   167         switch (mCompositionState) {
   168             case eCompositionState_NotComposing:
   169                 return "NotComposing";
   170             case eCompositionState_CompositionStartDispatched:
   171                 return "CompositionStartDispatched";
   172             case eCompositionState_TextEventDispatched:
   173                 return "TextEventDispatched";
   174             case eCompositionState_CommitTextEventDispatched:
   175                 return "CommitTextEventDispatched";
   176             default:
   177                 return "InvaildState";
   178         }
   179     }
   180 #endif // PR_LOGGING
   183     // mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
   184     // it's set to FALSE when we call gtk_im_context_focus_out().
   185     bool mIsIMFocused;
   186     // mFilterKeyEvent is used by OnKeyEvent().  If the commit event should
   187     // be processed as simple key event, this is set to TRUE by the commit
   188     // handler.
   189     bool mFilterKeyEvent;
   190     // When mIgnoreNativeCompositionEvent is TRUE, all native composition
   191     // should be ignored except that the compositon should be restarted in
   192     // another content (nsIContent).  Don't refer this value directly, use
   193     // ShouldIgnoreNativeCompositionEvent().
   194     bool mIgnoreNativeCompositionEvent;
   195     // mKeyDownEventWasSent is used by OnKeyEvent() and
   196     // DispatchCompositionStart().  DispatchCompositionStart() dispatches
   197     // a keydown event if the composition start is caused by a native
   198     // keypress event.  If this is true, the keydown event has been dispatched.
   199     // Then, DispatchCompositionStart() doesn't dispatch keydown event.
   200     bool mKeyDownEventWasSent;
   202     // sLastFocusedModule is a pointer to the last focused instance of this
   203     // class.  When a instance is destroyed and sLastFocusedModule refers it,
   204     // this is cleared.  So, this refers valid pointer always.
   205     static nsGtkIMModule* sLastFocusedModule;
   207     // sUseSimpleContext indeicates if password editors and editors with
   208     // |ime-mode: disabled;| should use GtkIMContextSimple.
   209     // If true, they use GtkIMContextSimple.  Otherwise, not.
   210     static bool sUseSimpleContext;
   212     // Callback methods for native IME events.  These methods should call
   213     // the related instance methods simply.
   214     static gboolean OnRetrieveSurroundingCallback(GtkIMContext  *aContext,
   215                                                   nsGtkIMModule *aModule);
   216     static gboolean OnDeleteSurroundingCallback(GtkIMContext  *aContext,
   217                                                 gint           aOffset,
   218                                                 gint           aNChars,
   219                                                 nsGtkIMModule *aModule);
   220     static void OnCommitCompositionCallback(GtkIMContext *aContext,
   221                                             const gchar *aString,
   222                                             nsGtkIMModule* aModule);
   223     static void OnChangeCompositionCallback(GtkIMContext *aContext,
   224                                             nsGtkIMModule* aModule);
   225     static void OnStartCompositionCallback(GtkIMContext *aContext,
   226                                            nsGtkIMModule* aModule);
   227     static void OnEndCompositionCallback(GtkIMContext *aContext,
   228                                          nsGtkIMModule* aModule);
   230     // The instance methods for the native IME events.
   231     gboolean OnRetrieveSurroundingNative(GtkIMContext  *aContext);
   232     gboolean OnDeleteSurroundingNative(GtkIMContext  *aContext,
   233                                        gint           aOffset,
   234                                        gint           aNChars);
   235     void OnCommitCompositionNative(GtkIMContext *aContext,
   236                                    const gchar *aString);
   237     void OnChangeCompositionNative(GtkIMContext *aContext);
   238     void OnStartCompositionNative(GtkIMContext *aContext);
   239     void OnEndCompositionNative(GtkIMContext *aContext);
   242     // GetContext() returns current IM context which is chosen by the enabled
   243     // state.  So, this means *current* IM context.
   244     GtkIMContext* GetContext();
   246     // "Editable" means the users can input characters. They may be not able to
   247     // use IMEs but they can use dead keys.
   248     // I.e., the focus is in the normal editors or the password editors or
   249     // the |ime-mode: disabled;| editors.
   250     bool IsEditable();
   252     // If the owner window and IM context have been destroyed, returns TRUE.
   253     bool IsDestroyed() { return !mOwnerWindow; }
   255     // Sets focus to the instance of this class.
   256     void Focus();
   258     // Steals focus from the instance of this class.
   259     void Blur();
   261     // Initializes the instance.
   262     void Init();
   264     // Reset the current composition of IME.  All native composition events
   265     // during this processing are ignored.
   266     void ResetIME();
   268     // Gets the current composition string by the native APIs.
   269     void GetCompositionString(nsAString &aCompositionString);
   271     // Generates our text range array from current composition string.
   272     already_AddRefed<mozilla::TextRangeArray> CreateTextRangeArray();
   274     // Sets the offset's cursor position to IME.
   275     void SetCursorPosition(uint32_t aTargetOffset);
   277     // Queries the current selection offset of the window.
   278     uint32_t GetSelectionOffset(nsWindow* aWindow);
   280     // Get current paragraph text content and cursor position
   281     nsresult GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos);
   283     // Delete text portion
   284     nsresult DeleteText(const int32_t aOffset, const uint32_t aNChars);
   286     // Initializes the GUI event.
   287     void InitEvent(mozilla::WidgetGUIEvent& aEvent);
   289     // Called before destroying the context to work around some platform bugs.
   290     void PrepareToDestroyContext(GtkIMContext *aContext);
   292     bool ShouldIgnoreNativeCompositionEvent();
   294     /**
   295      *  WARNING:
   296      *    Following methods dispatch gecko events.  Then, the focused widget
   297      *    can be destroyed, and also it can be stolen focus.  If they returns
   298      *    FALSE, callers cannot continue the composition.
   299      *      - CommitCompositionBy
   300      *      - DispatchCompositionStart
   301      *      - DispatchCompositionEnd
   302      *      - DispatchTextEvent
   303      */
   305     // Commits the current composition by the aString.
   306     bool CommitCompositionBy(const nsAString& aString);
   308     // Dispatches a composition start event or a composition end event.
   309     bool DispatchCompositionStart();
   310     bool DispatchCompositionEnd();
   312     // Dispatches a text event.  If aIsCommit is TRUE, dispatches a committed
   313     // text event.  Otherwise, dispatches a composing text event.
   314     bool DispatchTextEvent(const nsAString& aCompositionString,
   315                            bool aIsCommit);
   317 };
   319 #endif // __nsGtkIMModule_h__

mercurial