OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CONTENT_BROWSER_RENDERER_HOST_GTK_IM_CONTEXT_WRAPPER_H_ | |
6 #define CONTENT_BROWSER_RENDERER_HOST_GTK_IM_CONTEXT_WRAPPER_H_ | |
7 | |
8 #include <gdk/gdk.h> | |
9 #include <pango/pango-attributes.h> | |
10 #include <vector> | |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/gtest_prod_util.h" | |
14 #include "base/strings/string16.h" | |
15 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
16 #include "ui/base/ime/composition_text.h" | |
17 #include "ui/base/ime/text_input_type.h" | |
18 | |
19 typedef struct _GtkIMContext GtkIMContext; | |
20 typedef struct _GtkWidget GtkWidget; | |
21 | |
22 namespace gfx { | |
23 class Rect; | |
24 } | |
25 | |
26 namespace content { | |
27 class RenderWidgetHostViewGtk; | |
28 struct NativeWebKeyboardEvent; | |
29 | |
30 // This class is a convenience wrapper for GtkIMContext. | |
31 // It creates and manages two GtkIMContext instances, one is GtkIMMulticontext, | |
32 // for plain text input box, another is GtkIMContextSimple, for password input | |
33 // box. | |
34 // | |
35 // This class is in charge of dispatching key events to these two GtkIMContext | |
36 // instances and handling signals emitted by them. Key events then will be | |
37 // forwarded to renderer along with input method results via corresponding host | |
38 // view. | |
39 // | |
40 // This class is used solely by RenderWidgetHostViewGtk. | |
41 class GtkIMContextWrapper { | |
42 public: | |
43 explicit GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view); | |
44 ~GtkIMContextWrapper(); | |
45 | |
46 // Processes a gdk key event received by |host_view|. | |
47 void ProcessKeyEvent(GdkEventKey* event); | |
48 | |
49 void UpdateInputMethodState(ui::TextInputType type, | |
50 bool can_compose_inline); | |
51 void UpdateCaretBounds(const gfx::Rect& caret_bounds); | |
52 void OnFocusIn(); | |
53 void OnFocusOut(); | |
54 bool is_focused() const { return is_focused_; } | |
55 | |
56 GtkWidget* BuildInputMethodsGtkMenu(); | |
57 | |
58 void CancelComposition(); | |
59 | |
60 void ConfirmComposition(); | |
61 | |
62 private: | |
63 // Check if a text needs commit by forwarding a char event instead of | |
64 // by confirming as a composition text. | |
65 bool NeedCommitByForwardingCharEvent() const; | |
66 | |
67 // Check if the input method returned any result, eg. preedit and commit text. | |
68 bool HasInputMethodResult() const; | |
69 | |
70 void ProcessFilteredKeyPressEvent(NativeWebKeyboardEvent* wke); | |
71 void ProcessUnfilteredKeyPressEvent(NativeWebKeyboardEvent* wke); | |
72 | |
73 // Processes result returned from input method after filtering a key event. | |
74 // |filtered| indicates if the key event was filtered by the input method. | |
75 void ProcessInputMethodResult(const GdkEventKey* event, bool filtered); | |
76 | |
77 // Real code of "commit" signal handler. | |
78 void HandleCommit(const base::string16& text); | |
79 | |
80 // Real code of "preedit-start" signal handler. | |
81 void HandlePreeditStart(); | |
82 | |
83 // Real code of "preedit-changed" signal handler. | |
84 void HandlePreeditChanged(const gchar* text, | |
85 PangoAttrList* attrs, | |
86 int cursor_position); | |
87 | |
88 // Real code of "preedit-end" signal handler. | |
89 void HandlePreeditEnd(); | |
90 | |
91 // Real code of "retrieve-surrounding" signal handler. | |
92 gboolean HandleRetrieveSurrounding(GtkIMContext* context); | |
93 | |
94 // Real code of "realize" signal handler, used for setting im context's client | |
95 // window. | |
96 void HandleHostViewRealize(GtkWidget* widget); | |
97 | |
98 // Real code of "unrealize" signal handler, used for unsetting im context's | |
99 // client window. | |
100 void HandleHostViewUnrealize(); | |
101 | |
102 // Sends a fake composition key event with specified event type. A composition | |
103 // key event is a key event with special key code 229. | |
104 void SendFakeCompositionKeyEvent(blink::WebInputEvent::Type type); | |
105 | |
106 // Signal handlers of GtkIMContext object. | |
107 static void HandleCommitThunk(GtkIMContext* context, gchar* text, | |
108 GtkIMContextWrapper* self); | |
109 static void HandlePreeditStartThunk(GtkIMContext* context, | |
110 GtkIMContextWrapper* self); | |
111 static void HandlePreeditChangedThunk(GtkIMContext* context, | |
112 GtkIMContextWrapper* self); | |
113 static void HandlePreeditEndThunk(GtkIMContext* context, | |
114 GtkIMContextWrapper* self); | |
115 static gboolean HandleRetrieveSurroundingThunk(GtkIMContext* context, | |
116 GtkIMContextWrapper* self); | |
117 | |
118 // Signal handlers connecting to |host_view_|'s native view widget. | |
119 static void HandleHostViewRealizeThunk(GtkWidget* widget, | |
120 GtkIMContextWrapper* self); | |
121 static void HandleHostViewUnrealizeThunk(GtkWidget* widget, | |
122 GtkIMContextWrapper* self); | |
123 | |
124 // The parent object. | |
125 RenderWidgetHostViewGtk* host_view_; | |
126 | |
127 // The GtkIMContext object. | |
128 // In terms of the DOM event specification Appendix A | |
129 // <http://www.w3.org/TR/DOM-Level-3-Events/keyset.html>, | |
130 // GTK uses a GtkIMContext object for the following two purposes: | |
131 // 1. Composing Latin characters (A.1.2), and; | |
132 // 2. Composing CJK characters with an IME (A.1.3). | |
133 // Many JavaScript pages assume composed Latin characters are dispatched to | |
134 // their onkeypress() handlers but not dispatched CJK characters composed | |
135 // with an IME. To emulate this behavior, we should monitor the status of | |
136 // this GtkIMContext object and prevent sending Char events when a | |
137 // GtkIMContext object sends a "commit" signal with the CJK characters | |
138 // composed by an IME. | |
139 GtkIMContext* context_; | |
140 | |
141 // A GtkIMContextSimple object, for supporting dead/compose keys when input | |
142 // method is disabled, eg. in password input box. | |
143 GtkIMContext* context_simple_; | |
144 | |
145 // Whether or not this widget is focused. | |
146 bool is_focused_; | |
147 | |
148 // Whether or not the above GtkIMContext is composing a text with an IME. | |
149 // This flag is used in "commit" signal handler of the GtkIMContext object, | |
150 // which determines how to submit the result text to WebKit according to this | |
151 // flag. | |
152 // If this flag is true or there are more than one characters in the result, | |
153 // then the result text will be committed to WebKit as a confirmed | |
154 // composition. Otherwise, it'll be forwarded as a key event. | |
155 // | |
156 // The GtkIMContext object sends a "preedit_start" before it starts composing | |
157 // a text and a "preedit_end" signal after it finishes composing it. | |
158 // "preedit_start" signal is monitored to turn it on. | |
159 // We don't monitor "preedit_end" signal to turn it off, because an input | |
160 // method may fire "preedit_end" signal before "commit" signal. | |
161 // A buggy input method may not fire "preedit_start" and/or "preedit_end" | |
162 // at all, so this flag will also be set to true when "preedit_changed" signal | |
163 // is fired with non-empty preedit text. | |
164 bool is_composing_text_; | |
165 | |
166 // Whether or not the IME is enabled. | |
167 bool is_enabled_; | |
168 | |
169 // Whether or not it's currently running inside key event handler. | |
170 // If it's true, then preedit-changed and commit handler will backup the | |
171 // preedit or commit text instead of sending them down to webkit. | |
172 // key event handler will send them later. | |
173 bool is_in_key_event_handler_; | |
174 | |
175 // The most recent composition text information retrieved from context_; | |
176 ui::CompositionText composition_; | |
177 | |
178 // Whether or not the composition has been changed since last key event. | |
179 bool is_composition_changed_; | |
180 | |
181 // Stores a copy of the most recent commit text received by commit signal | |
182 // handler. | |
183 base::string16 commit_text_; | |
184 | |
185 // If it's true then the next "commit" signal will be suppressed. | |
186 // It's only used to workaround http://crbug.com/50485. | |
187 // TODO(suzhe): Remove it after input methods get fixed. | |
188 bool suppress_next_commit_; | |
189 | |
190 // Information of the last key event, for working around | |
191 // http://crosbug.com/6582 | |
192 int last_key_code_; | |
193 bool last_key_was_up_; | |
194 bool last_key_filtered_no_result_; | |
195 | |
196 DISALLOW_COPY_AND_ASSIGN(GtkIMContextWrapper); | |
197 }; | |
198 | |
199 } // namespace content | |
200 | |
201 #endif // CONTENT_BROWSER_RENDERER_HOST_GTK_IM_CONTEXT_WRAPPER_H_ | |
OLD | NEW |