From 07e654510f7646776a81afea88d1a1b4d5b06ffc Mon Sep 17 00:00:00 2001 From: Victor Sergienko Date: Wed, 18 Apr 2018 01:08:49 -0700 Subject: [PATCH] =?UTF-8?q?#2782=20Crash=20when=20using=20composing=20like?= =?UTF-8?q?=20=CB=87=20and=20'=20in=20lobby=20on=20macOS.=20Some=20backsto?= =?UTF-8?q?ry:=20https://github.com/wesnoth/wesnoth/pull/2644#issuecomment?= =?UTF-8?q?-382298822?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry-picked from commit 16cd19873db9686c54b1c5d3ba2d5a17d431d145) --- src/gui/core/event/handler.cpp | 4 ++-- src/gui/widgets/chatbox.cpp | 2 +- src/gui/widgets/text_box_base.cpp | 37 +++++++++++++++++++++---------- src/gui/widgets/text_box_base.hpp | 3 ++- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/gui/core/event/handler.cpp b/src/gui/core/event/handler.cpp index 12c5c80a456..fc682b30a9c 100644 --- a/src/gui/core/event/handler.cpp +++ b/src/gui/core/event/handler.cpp @@ -730,12 +730,12 @@ void sdl_event_handler::text_input(const std::string& unicode) } } -void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t end) +void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t len) { if(dispatcher* dispatcher = keyboard_dispatcher()) { dispatcher->fire(SDL_TEXT_EDITING, dynamic_cast(*dispatcher), - unicode, start, end); + unicode, start, len); } } diff --git a/src/gui/widgets/chatbox.cpp b/src/gui/widgets/chatbox.cpp index b3000b5f189..5e42ade5620 100644 --- a/src/gui/widgets/chatbox.cpp +++ b/src/gui/widgets/chatbox.cpp @@ -138,7 +138,7 @@ void chatbox::switch_to_window(std::size_t id) void chatbox::chat_input_keypress_callback(const SDL_Keycode key) { std::string input = chat_input_->get_value(); - if(input.empty()) { + if(input.empty() || chat_input_->is_composing()) { return; } diff --git a/src/gui/widgets/text_box_base.cpp b/src/gui/widgets/text_box_base.cpp index 4e5a236df82..af9b6d88960 100644 --- a/src/gui/widgets/text_box_base.cpp +++ b/src/gui/widgets/text_box_base.cpp @@ -54,7 +54,7 @@ text_box_base::text_box_base(const implementation::builder_styled_widget& builde connect_signal(std::bind( &text_box_base::signal_handler_sdl_key_down, this, _2, _3, _5, _6)); connect_signal(std::bind(&text_box_base::handle_commit, this, _3, _5)); - connect_signal(std::bind(&text_box_base::handle_editing, this, _3, _5, _6)); + connect_signal(std::bind(&text_box_base::handle_editing, this, _3, _5, _6, _7)); connect_signal(std::bind( &text_box_base::signal_handler_receive_keyboard_focus, this, _2)); @@ -429,11 +429,10 @@ void text_box_base::handle_commit(bool& handled, const std::string& unicode) if(unicode.size() > 1 || unicode[0] != 0) { handled = true; if(is_composing()) { - set_selection(ime_start_point_ + get_composition_length(), 0); + set_selection(ime_start_point_, get_composition_length()); ime_composing_ = false; - } else { - insert_char(unicode); } + insert_char(unicode); fire(event::NOTIFY_MODIFIED, *this, nullptr); if(text_changed_callback_) { @@ -442,7 +441,14 @@ void text_box_base::handle_commit(bool& handled, const std::string& unicode) } } -void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start) +/** + * SDL_TEXTEDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput + * @param handled + * @param unicode event.text.text, in SDL_TEXTEDITING is't the "composition" piece. + * @param start event.edit.start + * @param length event.edit.length + */ +void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len) { if(unicode.size() > 1 || unicode[0] != 0) { handled = true; @@ -463,21 +469,28 @@ void text_box_base::handle_editing(bool& handled, const std::string& unicode, in SDL_SetTextInputRect(&rect); } +#ifdef __unix__ // In SDL_TextEditingEvent, size of editing_text is limited - // If length of composition text is more than the limit, it is separated to multiple SDL_TextEditingEvent + // If length of composition text is more than the limit, + // Linux (ibus) implementation of SDL separates it into multiple + // SDL_TextEditingEvent. // start is start position of the separated event in entire composition text if(start == 0) { text_.set_text(text_cached_, false); } text_.insert_text(ime_start_point_ + start, unicode); +#else + std::string new_text(text_cached_); + utf8::insert(new_text, ime_start_point_, unicode); + text_.set_text(new_text, false); + +#endif + int maximum_length = text_.get_length(); // Update status - set_cursor(ime_start_point_, false); - int ime_length = get_composition_length(); - if(ime_length > 0) { - int maximum_length = text_.get_maximum_length(); - int cursor_end = std::min(maximum_length, ime_start_point_ + ime_length); - set_cursor(cursor_end, true); + set_cursor(std::min(maximum_length, ime_start_point_ + start), false); + if(len > 0) { + set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true); } update_canvas(); set_is_dirty(true); diff --git a/src/gui/widgets/text_box_base.hpp b/src/gui/widgets/text_box_base.hpp index 3692ee5988e..19589ef0044 100644 --- a/src/gui/widgets/text_box_base.hpp +++ b/src/gui/widgets/text_box_base.hpp @@ -484,7 +484,8 @@ protected: const std::string& unicode); virtual void handle_editing(bool& handled, const std::string& unicode, - int32_t start); + int32_t start, + int32_t length); private: /**