diff options
Diffstat (limited to 'scene/gui/text_edit.cpp')
-rw-r--r-- | scene/gui/text_edit.cpp | 136 |
1 files changed, 81 insertions, 55 deletions
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 95dc50f203..f8bd65ae06 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1489,14 +1489,7 @@ void TextEdit::_notification(int p_what) { } if (has_focus()) { - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { - DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); - Point2 pos = get_global_position() + get_caret_draw_pos(); - if (get_window()->get_embedder()) { - pos += get_viewport()->get_popup_base_transform().get_origin(); - } - DisplayServer::get_singleton()->window_set_ime_position(pos, get_viewport()->get_window_id()); - } + _update_ime_window_position(); } } break; @@ -1507,14 +1500,7 @@ void TextEdit::_notification(int p_what) { draw_caret = true; } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { - DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); - Point2 pos = get_global_position() + get_caret_draw_pos(); - if (get_window()->get_embedder()) { - pos += get_viewport()->get_popup_base_transform().get_origin(); - } - DisplayServer::get_singleton()->window_set_ime_position(pos, get_viewport()->get_window_id()); - } + _update_ime_window_position(); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) { int caret_start = -1; @@ -1541,17 +1527,7 @@ void TextEdit::_notification(int p_what) { caret_blink_timer->stop(); } - if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { - DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); - DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); - } - if (!ime_text.is_empty()) { - ime_text = ""; - ime_selection = Point2(); - for (int i = 0; i < carets.size(); i++) { - text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, ime_text); - } - } + apply_ime(); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) { DisplayServer::get_singleton()->virtual_keyboard_hide(); @@ -1571,15 +1547,8 @@ void TextEdit::_notification(int p_what) { delete_selection(); } - for (int i = 0; i < carets.size(); i++) { - String t; - if (get_caret_column(i) >= 0) { - t = text[get_caret_line(i)].substr(0, get_caret_column(i)) + ime_text + text[get_caret_line(i)].substr(get_caret_column(i), text[get_caret_line(i)].length()); - } else { - t = ime_text; - } - text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, t, structured_text_parser(st_parser, st_args, t)); - } + _update_ime_text(); + adjust_viewport_to_caret(0); queue_redraw(); } } break; @@ -1681,10 +1650,6 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; } - if (ime_text.length() != 0) { - // Ignore mouse clicks in IME input mode. - return; - } if (mb->is_pressed()) { if (mb->get_button_index() == MouseButton::WHEEL_UP && !mb->is_command_or_control_pressed()) { @@ -1718,6 +1683,8 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->get_button_index() == MouseButton::LEFT) { _reset_caret_blink_timer(); + apply_ime(); + Point2i pos = get_line_column_at_pos(mpos); int row = pos.y; int col = pos.x; @@ -1865,11 +1832,13 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MouseButton::MIDDLE && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { + apply_ime(); paste_primary_clipboard(); } if (mb->get_button_index() == MouseButton::RIGHT && (context_menu_enabled || is_move_caret_on_right_click_enabled())) { _reset_caret_blink_timer(); + apply_ime(); Point2i pos = get_line_column_at_pos(mpos); int row = pos.y; @@ -1909,6 +1878,11 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } } } else { + if (has_ime_text()) { + // Ignore mouse up in IME input mode. + return; + } + if (mb->get_button_index() == MouseButton::LEFT) { if (selection_drag_attempt && is_mouse_over_selection()) { remove_secondary_carets(); @@ -1967,7 +1941,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { _update_minimap_drag(); } - if (!dragging_minimap) { + if (!dragging_minimap && !has_ime_text()) { switch (selecting_mode) { case SelectionMode::SELECTION_MODE_POINTER: { _update_selection_mode_pointer(); @@ -2012,6 +1986,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (drag_action && can_drop_data(mpos, get_viewport()->gui_get_drag_data())) { + apply_ime(); drag_caret_force_displayed = true; Point2i pos = get_line_column_at_pos(get_local_mouse_pos()); set_caret_line(pos.y, false, true, 0, 0); @@ -3030,6 +3005,43 @@ void TextEdit::_update_caches() { } } +void TextEdit::_close_ime_window() { + if (get_viewport()->get_window_id() == DisplayServer::INVALID_WINDOW_ID || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { + return; + } + DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); + DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); +} + +void TextEdit::_update_ime_window_position() { + if (get_viewport()->get_window_id() == DisplayServer::INVALID_WINDOW_ID || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { + return; + } + DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); + Point2 pos = get_global_position() + get_caret_draw_pos(); + if (get_window()->get_embedder()) { + pos += get_viewport()->get_popup_base_transform().get_origin(); + } + // The window will move to the updated position the next time the IME is updated, not immediately. + DisplayServer::get_singleton()->window_set_ime_position(pos, get_viewport()->get_window_id()); +} + +void TextEdit::_update_ime_text() { + if (has_ime_text()) { + // Update text to visually include IME text. + for (int i = 0; i < get_caret_count(); i++) { + String text_with_ime = text[get_caret_line(i)].substr(0, get_caret_column(i)) + ime_text + text[get_caret_line(i)].substr(get_caret_column(i), text[get_caret_line(i)].length()); + text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, text_with_ime, structured_text_parser(st_parser, st_args, text_with_ime)); + } + } else { + // Reset text. + for (int i = 0; i < get_caret_count(); i++) { + text.invalidate_cache(get_caret_line(i), get_caret_column(i), true); + } + } + queue_redraw(); +} + /* General overrides. */ Size2 TextEdit::get_minimum_size() const { Size2 size = theme_cache.style_normal->get_minimum_size(); @@ -3189,6 +3201,26 @@ bool TextEdit::has_ime_text() const { return !ime_text.is_empty(); } +void TextEdit::cancel_ime() { + if (!has_ime_text()) { + return; + } + ime_text = String(); + ime_selection = Point2(); + _close_ime_window(); + _update_ime_text(); +} + +void TextEdit::apply_ime() { + if (!has_ime_text()) { + return; + } + // Force apply the current IME text. + String insert_ime_text = ime_text; + cancel_ime(); + insert_text_at_caret(insert_ime_text); +} + void TextEdit::set_editable(const bool p_editable) { if (editable == p_editable) { return; @@ -3568,16 +3600,8 @@ void TextEdit::insert_text_at_caret(const String &p_text, int p_caret) { adjust_carets_after_edit(i, new_line, new_column, from_line, from_col); } - if (!ime_text.is_empty()) { - for (int i = 0; i < carets.size(); i++) { - String t; - if (get_caret_column(i) >= 0) { - t = text[get_caret_line(i)].substr(0, get_caret_column(i)) + ime_text + text[get_caret_line(i)].substr(get_caret_column(i), text[get_caret_line(i)].length()); - } else { - t = ime_text; - } - text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, t, structured_text_parser(st_parser, st_args, t)); - } + if (has_ime_text()) { + _update_ime_text(); } end_complex_operation(); @@ -5560,14 +5584,14 @@ void TextEdit::adjust_viewport_to_caret(int p_caret) { Vector2i caret_pos; // Get position of the start of caret. - if (ime_text.length() != 0 && ime_selection.x != 0) { + if (has_ime_text() && ime_selection.x != 0) { caret_pos.x = _get_column_x_offset_for_line(get_caret_column(p_caret) + ime_selection.x, get_caret_line(p_caret), get_caret_column(p_caret)); } else { caret_pos.x = _get_column_x_offset_for_line(get_caret_column(p_caret), get_caret_line(p_caret), get_caret_column(p_caret)); } // Get position of the end of caret. - if (ime_text.length() != 0) { + if (has_ime_text()) { if (ime_selection.y != 0) { caret_pos.y = _get_column_x_offset_for_line(get_caret_column(p_caret) + ime_selection.x + ime_selection.y, get_caret_line(p_caret), get_caret_column(p_caret)); } else { @@ -5612,14 +5636,14 @@ void TextEdit::center_viewport_to_caret(int p_caret) { Vector2i caret_pos; // Get position of the start of caret. - if (ime_text.length() != 0 && ime_selection.x != 0) { + if (has_ime_text() && ime_selection.x != 0) { caret_pos.x = _get_column_x_offset_for_line(get_caret_column(p_caret) + ime_selection.x, get_caret_line(p_caret), get_caret_column(p_caret)); } else { caret_pos.x = _get_column_x_offset_for_line(get_caret_column(p_caret), get_caret_line(p_caret), get_caret_column(p_caret)); } // Get position of the end of caret. - if (ime_text.length() != 0) { + if (has_ime_text()) { if (ime_selection.y != 0) { caret_pos.y = _get_column_x_offset_for_line(get_caret_column(p_caret) + ime_selection.x + ime_selection.y, get_caret_line(p_caret), get_caret_column(p_caret)); } else { @@ -6029,6 +6053,8 @@ void TextEdit::_bind_methods() { /* Text */ // Text properties ClassDB::bind_method(D_METHOD("has_ime_text"), &TextEdit::has_ime_text); + ClassDB::bind_method(D_METHOD("cancel_ime"), &TextEdit::cancel_ime); + ClassDB::bind_method(D_METHOD("apply_ime"), &TextEdit::apply_ime); ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &TextEdit::set_editable); ClassDB::bind_method(D_METHOD("is_editable"), &TextEdit::is_editable); |