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