widget/gtk/nsGtkIMModule.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gtk/nsGtkIMModule.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,319 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim:expandtab:shiftwidth=4:tabstop=4:
     1.6 + */
     1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#ifndef __nsGtkIMModule_h__
    1.12 +#define __nsGtkIMModule_h__
    1.13 +
    1.14 +#include <gdk/gdk.h>
    1.15 +#include <gtk/gtk.h>
    1.16 +
    1.17 +#include "nsString.h"
    1.18 +#include "nsAutoPtr.h"
    1.19 +#include "nsCOMPtr.h"
    1.20 +#include "nsTArray.h"
    1.21 +#include "nsIWidget.h"
    1.22 +#include "mozilla/EventForwards.h"
    1.23 +
    1.24 +class nsWindow;
    1.25 +
    1.26 +class nsGtkIMModule
    1.27 +{
    1.28 +protected:
    1.29 +    typedef mozilla::widget::InputContext InputContext;
    1.30 +    typedef mozilla::widget::InputContextAction InputContextAction;
    1.31 +
    1.32 +public:
    1.33 +    nsrefcnt AddRef()
    1.34 +    {
    1.35 +        NS_PRECONDITION(int32_t(mRefCnt) >= 0, "mRefCnt is negative");
    1.36 +        ++mRefCnt;
    1.37 +        NS_LOG_ADDREF(this, mRefCnt, "nsGtkIMModule", sizeof(*this));
    1.38 +        return mRefCnt;
    1.39 +    }
    1.40 +    nsrefcnt Release()
    1.41 +    {
    1.42 +        NS_PRECONDITION(mRefCnt != 0, "mRefCnt is alrady zero");
    1.43 +        --mRefCnt;
    1.44 +        NS_LOG_RELEASE(this, mRefCnt, "nsGtkIMModule");
    1.45 +        if (mRefCnt == 0) {
    1.46 +            mRefCnt = 1; /* stabilize */
    1.47 +            delete this;
    1.48 +            return 0;
    1.49 +        }
    1.50 +        return mRefCnt;
    1.51 +    }
    1.52 +
    1.53 +protected:
    1.54 +    nsAutoRefCnt mRefCnt;
    1.55 +
    1.56 +public:
    1.57 +    // aOwnerWindow is a pointer of the owner window.  When aOwnerWindow is
    1.58 +    // destroyed, the related IME contexts are released (i.e., IME cannot be
    1.59 +    // used with the instance after that).
    1.60 +    nsGtkIMModule(nsWindow* aOwnerWindow);
    1.61 +    ~nsGtkIMModule();
    1.62 +
    1.63 +    // "Enabled" means the users can use all IMEs.
    1.64 +    // I.e., the focus is in the normal editors.
    1.65 +    bool IsEnabled();
    1.66 +
    1.67 +    // OnFocusWindow is a notification that aWindow is going to be focused.
    1.68 +    void OnFocusWindow(nsWindow* aWindow);
    1.69 +    // OnBlurWindow is a notification that aWindow is going to be unfocused.
    1.70 +    void OnBlurWindow(nsWindow* aWindow);
    1.71 +    // OnDestroyWindow is a notification that aWindow is going to be destroyed.
    1.72 +    void OnDestroyWindow(nsWindow* aWindow);
    1.73 +    // OnFocusChangeInGecko is a notification that an editor gets focus.
    1.74 +    void OnFocusChangeInGecko(bool aFocus);
    1.75 +
    1.76 +    // OnKeyEvent is called when aWindow gets a native key press event or a
    1.77 +    // native key release event.  If this returns TRUE, the key event was
    1.78 +    // filtered by IME.  Otherwise, this returns FALSE.
    1.79 +    // NOTE: When the keypress event starts composition, this returns TRUE but
    1.80 +    //       this dispatches keydown event before compositionstart event.
    1.81 +    bool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent,
    1.82 +                      bool aKeyDownEventWasSent = false);
    1.83 +
    1.84 +    // IME related nsIWidget methods.
    1.85 +    nsresult CommitIMEComposition(nsWindow* aCaller);
    1.86 +    void SetInputContext(nsWindow* aCaller,
    1.87 +                         const InputContext* aContext,
    1.88 +                         const InputContextAction* aAction);
    1.89 +    InputContext GetInputContext();
    1.90 +    nsresult CancelIMEComposition(nsWindow* aCaller);
    1.91 +    void OnUpdateComposition();
    1.92 +
    1.93 +    // If a software keyboard has been opened, this returns TRUE.
    1.94 +    // Otherwise, FALSE.
    1.95 +    static bool IsVirtualKeyboardOpened();
    1.96 +
    1.97 +protected:
    1.98 +    // Owner of an instance of this class. This should be top level window.
    1.99 +    // The owner window must release the contexts when it's destroyed because
   1.100 +    // the IME contexts need the native window.  If OnDestroyWindow() is called
   1.101 +    // with the owner window, it'll release IME contexts.  Otherwise, it'll
   1.102 +    // just clean up any existing composition if it's related to the destroying
   1.103 +    // child window.
   1.104 +    nsWindow* mOwnerWindow;
   1.105 +
   1.106 +    // A last focused window in this class's context.
   1.107 +    nsWindow* mLastFocusedWindow;
   1.108 +
   1.109 +    // Actual context. This is used for handling the user's input.
   1.110 +    GtkIMContext       *mContext;
   1.111 +
   1.112 +    // mSimpleContext is used for the password field and
   1.113 +    // the |ime-mode: disabled;| editors if sUseSimpleContext is true.
   1.114 +    // These editors disable IME.  But dead keys should work.  Fortunately,
   1.115 +    // the simple IM context of GTK2 support only them.
   1.116 +    GtkIMContext       *mSimpleContext;
   1.117 +
   1.118 +    // mDummyContext is a dummy context and will be used in Focus()
   1.119 +    // when the state of mEnabled means disabled.  This context's IME state is
   1.120 +    // always "closed", so it closes IME forcedly.
   1.121 +    GtkIMContext       *mDummyContext;
   1.122 +
   1.123 +    // IME enabled state and other things defined in InputContext.
   1.124 +    // Use following helper methods if you don't need the detail of the status.
   1.125 +    InputContext mInputContext;
   1.126 +
   1.127 +    // mCompositionStart is the start offset of the composition string in the
   1.128 +    // current content.  When <textarea> or <input> have focus, it means offset
   1.129 +    // from the first character of them.  When a HTML editor has focus, it
   1.130 +    // means offset from the first character of the root element of the editor.
   1.131 +    uint32_t mCompositionStart;
   1.132 +
   1.133 +    // mDispatchedCompositionString is the latest composition string which
   1.134 +    // was dispatched by compositionupdate event.
   1.135 +    nsString mDispatchedCompositionString;
   1.136 +
   1.137 +    // mSelectedString is the selected string which was removed by first
   1.138 +    // text event.
   1.139 +    nsString mSelectedString;
   1.140 +
   1.141 +    // OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
   1.142 +    // event.
   1.143 +    GdkEventKey* mProcessingKeyEvent;
   1.144 +
   1.145 +    // current target offset of IME composition
   1.146 +    uint32_t mCompositionTargetOffset;
   1.147 +
   1.148 +    // mCompositionState indicates current status of composition.
   1.149 +    enum eCompositionState {
   1.150 +        eCompositionState_NotComposing,
   1.151 +        eCompositionState_CompositionStartDispatched,
   1.152 +        eCompositionState_TextEventDispatched,
   1.153 +        eCompositionState_CommitTextEventDispatched
   1.154 +    };
   1.155 +    eCompositionState mCompositionState;
   1.156 +
   1.157 +    bool IsComposing()
   1.158 +    {
   1.159 +        return (mCompositionState != eCompositionState_NotComposing);
   1.160 +    }
   1.161 +
   1.162 +    bool EditorHasCompositionString()
   1.163 +    {
   1.164 +        return (mCompositionState == eCompositionState_TextEventDispatched);
   1.165 +    }
   1.166 +
   1.167 +#ifdef PR_LOGGING
   1.168 +    const char* GetCompositionStateName()
   1.169 +    {
   1.170 +        switch (mCompositionState) {
   1.171 +            case eCompositionState_NotComposing:
   1.172 +                return "NotComposing";
   1.173 +            case eCompositionState_CompositionStartDispatched:
   1.174 +                return "CompositionStartDispatched";
   1.175 +            case eCompositionState_TextEventDispatched:
   1.176 +                return "TextEventDispatched";
   1.177 +            case eCompositionState_CommitTextEventDispatched:
   1.178 +                return "CommitTextEventDispatched";
   1.179 +            default:
   1.180 +                return "InvaildState";
   1.181 +        }
   1.182 +    }
   1.183 +#endif // PR_LOGGING
   1.184 +
   1.185 +
   1.186 +    // mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
   1.187 +    // it's set to FALSE when we call gtk_im_context_focus_out().
   1.188 +    bool mIsIMFocused;
   1.189 +    // mFilterKeyEvent is used by OnKeyEvent().  If the commit event should
   1.190 +    // be processed as simple key event, this is set to TRUE by the commit
   1.191 +    // handler.
   1.192 +    bool mFilterKeyEvent;
   1.193 +    // When mIgnoreNativeCompositionEvent is TRUE, all native composition
   1.194 +    // should be ignored except that the compositon should be restarted in
   1.195 +    // another content (nsIContent).  Don't refer this value directly, use
   1.196 +    // ShouldIgnoreNativeCompositionEvent().
   1.197 +    bool mIgnoreNativeCompositionEvent;
   1.198 +    // mKeyDownEventWasSent is used by OnKeyEvent() and
   1.199 +    // DispatchCompositionStart().  DispatchCompositionStart() dispatches
   1.200 +    // a keydown event if the composition start is caused by a native
   1.201 +    // keypress event.  If this is true, the keydown event has been dispatched.
   1.202 +    // Then, DispatchCompositionStart() doesn't dispatch keydown event.
   1.203 +    bool mKeyDownEventWasSent;
   1.204 +
   1.205 +    // sLastFocusedModule is a pointer to the last focused instance of this
   1.206 +    // class.  When a instance is destroyed and sLastFocusedModule refers it,
   1.207 +    // this is cleared.  So, this refers valid pointer always.
   1.208 +    static nsGtkIMModule* sLastFocusedModule;
   1.209 +
   1.210 +    // sUseSimpleContext indeicates if password editors and editors with
   1.211 +    // |ime-mode: disabled;| should use GtkIMContextSimple.
   1.212 +    // If true, they use GtkIMContextSimple.  Otherwise, not.
   1.213 +    static bool sUseSimpleContext;
   1.214 +
   1.215 +    // Callback methods for native IME events.  These methods should call
   1.216 +    // the related instance methods simply.
   1.217 +    static gboolean OnRetrieveSurroundingCallback(GtkIMContext  *aContext,
   1.218 +                                                  nsGtkIMModule *aModule);
   1.219 +    static gboolean OnDeleteSurroundingCallback(GtkIMContext  *aContext,
   1.220 +                                                gint           aOffset,
   1.221 +                                                gint           aNChars,
   1.222 +                                                nsGtkIMModule *aModule);
   1.223 +    static void OnCommitCompositionCallback(GtkIMContext *aContext,
   1.224 +                                            const gchar *aString,
   1.225 +                                            nsGtkIMModule* aModule);
   1.226 +    static void OnChangeCompositionCallback(GtkIMContext *aContext,
   1.227 +                                            nsGtkIMModule* aModule);
   1.228 +    static void OnStartCompositionCallback(GtkIMContext *aContext,
   1.229 +                                           nsGtkIMModule* aModule);
   1.230 +    static void OnEndCompositionCallback(GtkIMContext *aContext,
   1.231 +                                         nsGtkIMModule* aModule);
   1.232 +
   1.233 +    // The instance methods for the native IME events.
   1.234 +    gboolean OnRetrieveSurroundingNative(GtkIMContext  *aContext);
   1.235 +    gboolean OnDeleteSurroundingNative(GtkIMContext  *aContext,
   1.236 +                                       gint           aOffset,
   1.237 +                                       gint           aNChars);
   1.238 +    void OnCommitCompositionNative(GtkIMContext *aContext,
   1.239 +                                   const gchar *aString);
   1.240 +    void OnChangeCompositionNative(GtkIMContext *aContext);
   1.241 +    void OnStartCompositionNative(GtkIMContext *aContext);
   1.242 +    void OnEndCompositionNative(GtkIMContext *aContext);
   1.243 +
   1.244 +
   1.245 +    // GetContext() returns current IM context which is chosen by the enabled
   1.246 +    // state.  So, this means *current* IM context.
   1.247 +    GtkIMContext* GetContext();
   1.248 +
   1.249 +    // "Editable" means the users can input characters. They may be not able to
   1.250 +    // use IMEs but they can use dead keys.
   1.251 +    // I.e., the focus is in the normal editors or the password editors or
   1.252 +    // the |ime-mode: disabled;| editors.
   1.253 +    bool IsEditable();
   1.254 +
   1.255 +    // If the owner window and IM context have been destroyed, returns TRUE.
   1.256 +    bool IsDestroyed() { return !mOwnerWindow; }
   1.257 +
   1.258 +    // Sets focus to the instance of this class.
   1.259 +    void Focus();
   1.260 +
   1.261 +    // Steals focus from the instance of this class.
   1.262 +    void Blur();
   1.263 +
   1.264 +    // Initializes the instance.
   1.265 +    void Init();
   1.266 +
   1.267 +    // Reset the current composition of IME.  All native composition events
   1.268 +    // during this processing are ignored.
   1.269 +    void ResetIME();
   1.270 +
   1.271 +    // Gets the current composition string by the native APIs.
   1.272 +    void GetCompositionString(nsAString &aCompositionString);
   1.273 +
   1.274 +    // Generates our text range array from current composition string.
   1.275 +    already_AddRefed<mozilla::TextRangeArray> CreateTextRangeArray();
   1.276 +
   1.277 +    // Sets the offset's cursor position to IME.
   1.278 +    void SetCursorPosition(uint32_t aTargetOffset);
   1.279 +
   1.280 +    // Queries the current selection offset of the window.
   1.281 +    uint32_t GetSelectionOffset(nsWindow* aWindow);
   1.282 +
   1.283 +    // Get current paragraph text content and cursor position
   1.284 +    nsresult GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos);
   1.285 +
   1.286 +    // Delete text portion
   1.287 +    nsresult DeleteText(const int32_t aOffset, const uint32_t aNChars);
   1.288 +
   1.289 +    // Initializes the GUI event.
   1.290 +    void InitEvent(mozilla::WidgetGUIEvent& aEvent);
   1.291 +
   1.292 +    // Called before destroying the context to work around some platform bugs.
   1.293 +    void PrepareToDestroyContext(GtkIMContext *aContext);
   1.294 +
   1.295 +    bool ShouldIgnoreNativeCompositionEvent();
   1.296 +
   1.297 +    /**
   1.298 +     *  WARNING:
   1.299 +     *    Following methods dispatch gecko events.  Then, the focused widget
   1.300 +     *    can be destroyed, and also it can be stolen focus.  If they returns
   1.301 +     *    FALSE, callers cannot continue the composition.
   1.302 +     *      - CommitCompositionBy
   1.303 +     *      - DispatchCompositionStart
   1.304 +     *      - DispatchCompositionEnd
   1.305 +     *      - DispatchTextEvent
   1.306 +     */
   1.307 +
   1.308 +    // Commits the current composition by the aString.
   1.309 +    bool CommitCompositionBy(const nsAString& aString);
   1.310 +
   1.311 +    // Dispatches a composition start event or a composition end event.
   1.312 +    bool DispatchCompositionStart();
   1.313 +    bool DispatchCompositionEnd();
   1.314 +
   1.315 +    // Dispatches a text event.  If aIsCommit is TRUE, dispatches a committed
   1.316 +    // text event.  Otherwise, dispatches a composing text event.
   1.317 +    bool DispatchTextEvent(const nsAString& aCompositionString,
   1.318 +                           bool aIsCommit);
   1.319 +
   1.320 +};
   1.321 +
   1.322 +#endif // __nsGtkIMModule_h__

mercurial