| 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 |