diff --git a/dep/imgui/include/imgui.h b/dep/imgui/include/imgui.h index 5fb41becc..543c135b6 100644 --- a/dep/imgui/include/imgui.h +++ b/dep/imgui/include/imgui.h @@ -1295,6 +1295,9 @@ enum ImGuiInputTextFlags_ // The CPU cost is very roughly proportional to text length, so a 10 KB buffer should cost about ten times less. ImGuiInputTextFlags_WordWrap = 1 << 24, // InputTextMultiline(): word-wrap lines that are too long. + // DuckStation additions + ImGuiInputTextFlags_AlwaysActivate = 1 << 25, // Force the widget to activate immediately. + // Obsolete names //ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior }; diff --git a/dep/imgui/src/imgui_widgets.cpp b/dep/imgui/src/imgui_widgets.cpp index dee968abf..02d4ed4be 100644 --- a/dep/imgui/src/imgui_widgets.cpp +++ b/dep/imgui/src/imgui_widgets.cpp @@ -4783,7 +4783,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ 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_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_reactivate); + const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || + input_requested_by_reactivate || (flags & ImGuiInputTextFlags_AlwaysActivate) != 0); const bool init_state = (init_make_active || user_scroll_active); if (init_reload_from_user_buf) { diff --git a/src/core/fullscreenui_widgets.cpp b/src/core/fullscreenui_widgets.cpp index 9f2863572..7bdea326a 100644 --- a/src/core/fullscreenui_widgets.cpp +++ b/src/core/fullscreenui_widgets.cpp @@ -4556,6 +4556,50 @@ bool FullscreenUI::SplitWindowIsNavWindow() return (nav_window && (nav_window == current_window || nav_window->ParentWindow == current_window)); } +bool FullscreenUI::InputTextWithIcon(const char* str_id, std::string_view icon, const char* hint, char* buf, + size_t buf_size, float width, float font_size, float font_weight, + ImGuiInputTextFlags flags /* = 0 */, + ImGuiInputTextCallback callback /* = nullptr */, void* user_data /* = nullptr */) +{ + const ImGuiStyle& style = ImGui::GetStyle(); + const ImVec2 icon_size = + UIStyle.Font->CalcTextSizeA(font_size, font_weight, std::numeric_limits::max(), 0.0f, IMSTR_START_END(icon)); + const float& icon_spacing = ImCeil(font_size * 0.5f); + + const ImVec2 box_min = ImGui::GetCursorScreenPos(); + const ImVec2 box_max = box_min + ImVec2(width, font_size + style.FramePadding.y * 2.0f); + const float box_rounding = ImCeil(font_size * 0.75f); + + ImGuiWindow* const win = ImGui::GetCurrentWindow(); + ImDrawList* const dl = win->DrawList; + dl->AddRectFilled(box_min, box_max, ImGui::GetColorU32(DarkerColor(UIStyle.PrimaryColor, 1.2f)), box_rounding); + + dl->AddText(UIStyle.Font, font_size, font_weight, box_min + style.FramePadding, ImGui::GetColorU32(ImGuiCol_Text), + IMSTR_START_END(icon)); + + ImGui::SetCursorScreenPos(ImVec2(box_min.x + style.FramePadding.x + icon_size.x + icon_spacing, box_min.y)); + ImGui::SetNextItemWidth(width - style.FramePadding.x * 2.0f - icon_size.x - icon_spacing); + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, style.FramePadding.y)); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_NavCursor, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_Text, UIStyle.PrimaryTextColor); + ImGui::PushFont(UIStyle.Font, font_size, font_weight); + + const bool result = ImGui::InputTextWithHint(str_id, hint, buf, buf_size, flags, callback, user_data); + + if (ImGui::IsItemFocused()) + dl->AddRect(box_min, box_max, ImGui::GetColorU32(ImGuiCol_Border), box_rounding, 0, LayoutScale(1.0f)); + + ImGui::PopFont(); + ImGui::PopStyleColor(3); + ImGui::PopStyleVar(3); + + return result; +} + FullscreenUI::PopupDialog::PopupDialog() = default; FullscreenUI::PopupDialog::~PopupDialog() = default; diff --git a/src/core/fullscreenui_widgets.h b/src/core/fullscreenui_widgets.h index eac88d8bb..73e3cc32f 100644 --- a/src/core/fullscreenui_widgets.h +++ b/src/core/fullscreenui_widgets.h @@ -530,6 +530,10 @@ bool WasSplitWindowChanged(); void FocusSplitWindowContent(); bool SplitWindowIsNavWindow(); +bool InputTextWithIcon(const char* str_id, std::string_view icon, const char* hint, char* buf, size_t buf_size, + float width, float font_size, float font_weight, ImGuiInputTextFlags flags = 0, + ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); + bool AreAnyWidgetsDialogOpen(); bool AreAnyWidgetsDialogInteractable();