From d5ec7cc296a074e8e2247ffc825c6d5c8647ed48 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 28 Sep 2022 15:47:42 +0400 Subject: [PATCH] Fix possible stack overflow crash on Windows. --- ui/widgets/time_input.cpp | 35 +++++++++++++++++++++++++++++++++-- ui/widgets/time_input.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/ui/widgets/time_input.cpp b/ui/widgets/time_input.cpp index d51a77b..d40aa26 100644 --- a/ui/widgets/time_input.cpp +++ b/ui/widgets/time_input.cpp @@ -7,6 +7,7 @@ #include "ui/widgets/time_input.h" #include "ui/widgets/fields/time_part_input.h" +#include "base/invoke_queued.h" #include #include @@ -146,7 +147,7 @@ void TimeInput::putNext(const object_ptr &field, QChar ch) { field->setCursorPosition(1); } field->onTextEdited(); - field->setFocus(); + setFocusQueued(field); } void TimeInput::erasePrevious(const object_ptr &field) { @@ -155,7 +156,37 @@ void TimeInput::erasePrevious(const object_ptr &field) { field->setCursorPosition(text.size() - 1); field->setText(text.mid(0, text.size() - 1)); } - field->setFocus(); + setFocusQueued(field); +} + +void TimeInput::setFocusQueued(const object_ptr &field) { + // There was a "Stack Overflow" crash in some input method handling. + // + // See https://github.com/telegramdesktop/tdesktop/issues/25129 + // + // The stack is something like: + // + // ... + // QApplicationPrivate::sendMouseEvent + // ---- + // QWidget::setFocus + // QWindow::focusObjectChanged + // QWindowsInputContext::setFocusObject + // QWindowsInputContext::reset + // QLineEdit::inputMethodEvent + // QWidgetLineControl::finishChange + // QLineEdit::textEdited + // MaskedInputField::onTextEdited + // TimePart::correctValue + // TimeInput::putNext + // ---- + // QWidget::setFocus + // QWindow::focusObjectChanged + // ... + // + // So we try to break this loop by focusing the widget async. + const auto raw = field.data(); + InvokeQueued(raw, [raw] { raw->setFocus(); }); } bool TimeInput::setFocusFast() { diff --git a/ui/widgets/time_input.h b/ui/widgets/time_input.h index e8edd5a..3bd9aec 100644 --- a/ui/widgets/time_input.h +++ b/ui/widgets/time_input.h @@ -43,6 +43,7 @@ private: void setInnerFocus(); void putNext(const object_ptr &field, QChar ch); void erasePrevious(const object_ptr &field); + void setFocusQueued(const object_ptr &field); void setErrorShown(bool error); void setFocused(bool focused); void startBorderAnimation();