| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "views/ime/input_method_gtk.h" | 5 #include "views/ime/input_method_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdk.h> | 7 #include <gdk/gdk.h> |
| 8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 } | 103 } |
| 104 | 104 |
| 105 void InputMethodGtk::OnBlur() { | 105 void InputMethodGtk::OnBlur() { |
| 106 DCHECK(widget_focused()); | 106 DCHECK(widget_focused()); |
| 107 ConfirmCompositionText(); | 107 ConfirmCompositionText(); |
| 108 InputMethodBase::OnBlur(); | 108 InputMethodBase::OnBlur(); |
| 109 UpdateContextFocusState(); | 109 UpdateContextFocusState(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void InputMethodGtk::DispatchKeyEvent(const KeyEvent& key) { | 112 void InputMethodGtk::DispatchKeyEvent(const KeyEvent& key) { |
| 113 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); |
| 113 suppress_next_result_ = false; | 114 suppress_next_result_ = false; |
| 114 | 115 |
| 115 // We should bypass |context_| and |context_simple_| only if there is no | 116 // We should bypass |context_| and |context_simple_| only if there is no |
| 116 // text input client is focused at all. Otherwise, we should always send the | 117 // text input client focused. Otherwise, always send the key event to either |
| 117 // key event to either |context_| or |context_simple_| even if the text input | 118 // |context_| or |context_simple_| even if the text input type is |
| 118 // type is ui::TEXT_INPUT_TYPE_NONE, to make sure we can get correct character | 119 // ui::TEXT_INPUT_TYPE_NONE, to make sure we can get correct character result. |
| 119 // result. | |
| 120 if (!GetTextInputClient()) { | 120 if (!GetTextInputClient()) { |
| 121 DispatchKeyEventPostIME(key); | 121 DispatchKeyEventPostIME(key); |
| 122 return; | 122 return; |
| 123 } | 123 } |
| 124 | 124 |
| 125 handling_key_event_ = true; | 125 handling_key_event_ = true; |
| 126 composition_changed_ = false; | 126 composition_changed_ = false; |
| 127 result_text_.clear(); | 127 result_text_.clear(); |
| 128 | 128 |
| 129 GdkEvent* event = key.native_event(); | 129 // If it's a fake key event, then we need to synthesize a GdkEventKey. |
| 130 DCHECK(!event || event->type == GDK_KEY_PRESS || | 130 GdkEvent* event = key.native_event() ? key.native_event() : |
| 131 event->type == GDK_KEY_RELEASE); | 131 SynthesizeGdkEventKey(key); |
| 132 | 132 gboolean filtered = gtk_im_context_filter_keypress( |
| 133 // If it's a fake key event, then we need to synthesis a GdkEventKey. | 133 context_focused_ ? context_ : context_simple_, &event->key); |
| 134 bool need_free_event = false; | |
| 135 if (!event) { | |
| 136 event = SynthesizeGdkEventKey(key); | |
| 137 need_free_event = true; | |
| 138 } | |
| 139 | |
| 140 gboolean filtered = false; | |
| 141 if (context_focused_) | |
| 142 filtered = gtk_im_context_filter_keypress(context_, &event->key); | |
| 143 else | |
| 144 filtered = gtk_im_context_filter_keypress(context_simple_, &event->key); | |
| 145 | 134 |
| 146 handling_key_event_ = false; | 135 handling_key_event_ = false; |
| 147 | 136 |
| 148 const View* old_focused_view = focused_view(); | 137 const View* old_focused_view = focused_view(); |
| 149 if (key.type() == ui::ET_KEY_PRESSED && filtered) | 138 if (key.type() == ui::ET_KEY_PRESSED && filtered) |
| 150 ProcessFilteredKeyPressEvent(key); | 139 ProcessFilteredKeyPressEvent(key); |
| 151 | 140 |
| 152 // In case the focus was changed by the key event. | 141 // Ensure no focus change from processing the key event. |
| 153 if (old_focused_view != focused_view()) | 142 if (old_focused_view == focused_view()) { |
| 154 return; | 143 if (HasInputMethodResult()) |
| 144 ProcessInputMethodResult(key, filtered); |
| 145 // Ensure no focus change sending input method results to the focused View. |
| 146 if (old_focused_view == focused_view()) { |
| 147 if (key.type() == ui::ET_KEY_PRESSED && !filtered) |
| 148 ProcessUnfilteredKeyPressEvent(key); |
| 149 else if (key.type() == ui::ET_KEY_RELEASED) |
| 150 DispatchKeyEventPostIME(key); |
| 151 } |
| 152 } |
| 155 | 153 |
| 156 if (HasInputMethodResult()) | 154 // Free the synthesized event if there was no underlying native event. |
| 157 ProcessInputMethodResult(key, filtered); | 155 if (event != key.native_event()) |
| 158 | |
| 159 // In case the focus was changed when sending input method results to the | |
| 160 // focused View. | |
| 161 if (old_focused_view != focused_view()) | |
| 162 return; | |
| 163 | |
| 164 if (key.type() == ui::ET_KEY_PRESSED && !filtered) | |
| 165 ProcessUnfilteredKeyPressEvent(key); | |
| 166 else if (key.type() == ui::ET_KEY_RELEASED) | |
| 167 DispatchKeyEventPostIME(key); | |
| 168 | |
| 169 if (need_free_event) | |
| 170 gdk_event_free(event); | 156 gdk_event_free(event); |
| 171 } | 157 } |
| 172 | 158 |
| 173 void InputMethodGtk::OnTextInputTypeChanged(View* view) { | 159 void InputMethodGtk::OnTextInputTypeChanged(View* view) { |
| 174 if (IsViewFocused(view)) { | 160 if (IsViewFocused(view)) { |
| 175 DCHECK(!composing_text_); | 161 DCHECK(!composing_text_); |
| 176 UpdateContextFocusState(); | 162 UpdateContextFocusState(); |
| 177 } | 163 } |
| 178 } | 164 } |
| 179 | 165 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 void InputMethodGtk::SendFakeProcessKeyEvent(bool pressed) const { | 339 void InputMethodGtk::SendFakeProcessKeyEvent(bool pressed) const { |
| 354 KeyEvent key(pressed ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, | 340 KeyEvent key(pressed ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, |
| 355 ui::VKEY_PROCESSKEY, 0); | 341 ui::VKEY_PROCESSKEY, 0); |
| 356 DispatchKeyEventPostIME(key); | 342 DispatchKeyEventPostIME(key); |
| 357 } | 343 } |
| 358 | 344 |
| 359 GdkEvent* InputMethodGtk::SynthesizeGdkEventKey(const KeyEvent& key) const { | 345 GdkEvent* InputMethodGtk::SynthesizeGdkEventKey(const KeyEvent& key) const { |
| 360 guint keyval = | 346 guint keyval = |
| 361 ui::GdkKeyCodeForWindowsKeyCode(key.key_code(), key.IsShiftDown()); | 347 ui::GdkKeyCodeForWindowsKeyCode(key.key_code(), key.IsShiftDown()); |
| 362 guint state = 0; | 348 guint state = 0; |
| 363 if (key.IsShiftDown()) | 349 state |= key.IsShiftDown() ? GDK_SHIFT_MASK : 0; |
| 364 state |= GDK_SHIFT_MASK; | 350 state |= key.IsControlDown() ? GDK_CONTROL_MASK : 0; |
| 365 if (key.IsControlDown()) | 351 state |= key.IsAltDown() ? GDK_MOD1_MASK : 0; |
| 366 state |= GDK_CONTROL_MASK; | 352 state |= key.IsCapsLockDown() ? GDK_LOCK_MASK : 0; |
| 367 if (key.IsAltDown()) | |
| 368 state |= GDK_MOD1_MASK; | |
| 369 if (key.IsCapsLockDown()) | |
| 370 state |= GDK_LOCK_MASK; | |
| 371 | 353 |
| 372 DCHECK(widget()->GetNativeView()->window); | 354 DCHECK(widget()->GetNativeView()->window); |
| 373 return ui::SynthesizeKeyEvent(widget()->GetNativeView()->window, | 355 return ui::SynthesizeKeyEvent(widget()->GetNativeView()->window, |
| 374 key.type() == ui::ET_KEY_PRESSED, | 356 key.type() == ui::ET_KEY_PRESSED, |
| 375 keyval, state); | 357 keyval, state); |
| 376 } | 358 } |
| 377 | 359 |
| 378 void InputMethodGtk::OnCommit(GtkIMContext* context, gchar* text) { | 360 void InputMethodGtk::OnCommit(GtkIMContext* context, gchar* text) { |
| 379 if (suppress_next_result_) { | 361 if (suppress_next_result_) { |
| 380 suppress_next_result_ = false; | 362 suppress_next_result_ = false; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 gtk_im_context_set_client_window(context_simple_, widget->window); | 440 gtk_im_context_set_client_window(context_simple_, widget->window); |
| 459 } | 441 } |
| 460 } | 442 } |
| 461 | 443 |
| 462 void InputMethodGtk::OnWidgetUnrealize(GtkWidget* widget) { | 444 void InputMethodGtk::OnWidgetUnrealize(GtkWidget* widget) { |
| 463 gtk_im_context_set_client_window(context_, NULL); | 445 gtk_im_context_set_client_window(context_, NULL); |
| 464 gtk_im_context_set_client_window(context_simple_, NULL); | 446 gtk_im_context_set_client_window(context_simple_, NULL); |
| 465 } | 447 } |
| 466 | 448 |
| 467 } // namespace views | 449 } // namespace views |
| OLD | NEW |