diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3dfeb941b..c69d92f79 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Other Changes: - InputText: - InputTextMultiline: fixed an issue processing deactivation logic when an active multi-line edit is clipped due to being out of view. + - Fixed a crash when toggling ReadOnly while active. (#9354) - Tables: - Fixed an issue reporting ideal size to parent window/container when both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested. (#9352, #7651) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d96c5711e..2880ed6ba 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4800,7 +4800,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf); - const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state. + const bool init_changed_specs_multiline = (state != NULL && (state->Stb->single_line != !is_multiline)); // state != NULL means its our state. + const bool init_changed_specs_readonly = (state != NULL && ((state->Flags ^ flags) & ImGuiInputTextFlags_ReadOnly)); // state != NULL means its our state. const bool init_make_active = (input_requested_by_user || input_requested_by_nav || input_requested_by_reactivate || user_scroll_finish); if (init_reload_from_user_buf) { @@ -4814,7 +4815,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ state->Stb->select_start = state->ReloadSelectionStart; state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below } - else if ((init_make_active && g.ActiveId != id) || init_changed_specs) + else if ((init_make_active && g.ActiveId != id) || init_changed_specs_multiline || init_changed_specs_readonly) { // Access state even if we don't own it yet. state = &g.InputTextState; @@ -4835,8 +4836,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Preserve cursor position and undo/redo stack if we come back to same widget // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? - bool recycle_state = (state->ID == id && !init_changed_specs); - if (recycle_state && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0))) + bool recycle_state = (state->ID == id && !init_changed_specs_multiline); + if (recycle_state && !init_changed_specs_readonly && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0))) recycle_state = false; // Start edition @@ -4945,13 +4946,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_password && !is_displaying_hint) PushPasswordFont(); - // Word-wrapping: attempt to keep cursor in view while resizing frame/parent - // FIXME-WORDWRAP: It would be better to preserve same relative offset. - if (is_wordwrap && state != NULL && state->ID == id && state->WrapWidth != wrap_width) + if (state != NULL && state->ID == id) { - state->CursorCenterY = true; - state->WrapWidth = wrap_width; - render_cursor = true; + state->Flags = flags; + + // Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset) + if (is_wordwrap && state->WrapWidth != wrap_width) + { + state->CursorCenterY = true; + state->WrapWidth = wrap_width; + render_cursor = true; + } } // Process mouse inputs and character inputs @@ -4960,7 +4965,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(state != NULL); state->EditedThisFrame = false; state->BufCapacity = buf_size; - state->Flags = flags; state->WrapWidth = wrap_width; // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.