widget/gtk/nsGtkIMModule.h

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:62c981200419
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/. */
7
8 #ifndef __nsGtkIMModule_h__
9 #define __nsGtkIMModule_h__
10
11 #include <gdk/gdk.h>
12 #include <gtk/gtk.h>
13
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"
20
21 class nsWindow;
22
23 class nsGtkIMModule
24 {
25 protected:
26 typedef mozilla::widget::InputContext InputContext;
27 typedef mozilla::widget::InputContextAction InputContextAction;
28
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 }
49
50 protected:
51 nsAutoRefCnt mRefCnt;
52
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();
59
60 // "Enabled" means the users can use all IMEs.
61 // I.e., the focus is in the normal editors.
62 bool IsEnabled();
63
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);
72
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);
80
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();
89
90 // If a software keyboard has been opened, this returns TRUE.
91 // Otherwise, FALSE.
92 static bool IsVirtualKeyboardOpened();
93
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;
102
103 // A last focused window in this class's context.
104 nsWindow* mLastFocusedWindow;
105
106 // Actual context. This is used for handling the user's input.
107 GtkIMContext *mContext;
108
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;
114
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;
119
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;
123
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;
129
130 // mDispatchedCompositionString is the latest composition string which
131 // was dispatched by compositionupdate event.
132 nsString mDispatchedCompositionString;
133
134 // mSelectedString is the selected string which was removed by first
135 // text event.
136 nsString mSelectedString;
137
138 // OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
139 // event.
140 GdkEventKey* mProcessingKeyEvent;
141
142 // current target offset of IME composition
143 uint32_t mCompositionTargetOffset;
144
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;
153
154 bool IsComposing()
155 {
156 return (mCompositionState != eCompositionState_NotComposing);
157 }
158
159 bool EditorHasCompositionString()
160 {
161 return (mCompositionState == eCompositionState_TextEventDispatched);
162 }
163
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
181
182
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;
201
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;
206
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;
211
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);
229
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);
240
241
242 // GetContext() returns current IM context which is chosen by the enabled
243 // state. So, this means *current* IM context.
244 GtkIMContext* GetContext();
245
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();
251
252 // If the owner window and IM context have been destroyed, returns TRUE.
253 bool IsDestroyed() { return !mOwnerWindow; }
254
255 // Sets focus to the instance of this class.
256 void Focus();
257
258 // Steals focus from the instance of this class.
259 void Blur();
260
261 // Initializes the instance.
262 void Init();
263
264 // Reset the current composition of IME. All native composition events
265 // during this processing are ignored.
266 void ResetIME();
267
268 // Gets the current composition string by the native APIs.
269 void GetCompositionString(nsAString &aCompositionString);
270
271 // Generates our text range array from current composition string.
272 already_AddRefed<mozilla::TextRangeArray> CreateTextRangeArray();
273
274 // Sets the offset's cursor position to IME.
275 void SetCursorPosition(uint32_t aTargetOffset);
276
277 // Queries the current selection offset of the window.
278 uint32_t GetSelectionOffset(nsWindow* aWindow);
279
280 // Get current paragraph text content and cursor position
281 nsresult GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos);
282
283 // Delete text portion
284 nsresult DeleteText(const int32_t aOffset, const uint32_t aNChars);
285
286 // Initializes the GUI event.
287 void InitEvent(mozilla::WidgetGUIEvent& aEvent);
288
289 // Called before destroying the context to work around some platform bugs.
290 void PrepareToDestroyContext(GtkIMContext *aContext);
291
292 bool ShouldIgnoreNativeCompositionEvent();
293
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 */
304
305 // Commits the current composition by the aString.
306 bool CommitCompositionBy(const nsAString& aString);
307
308 // Dispatches a composition start event or a composition end event.
309 bool DispatchCompositionStart();
310 bool DispatchCompositionEnd();
311
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);
316
317 };
318
319 #endif // __nsGtkIMModule_h__

mercurial