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