From 71efd10c83c50620c00aa5ae238360b70b975e2b Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Tue, 4 Dec 2018 11:19:28 +0400 Subject: [PATCH] Fix crash on layer -> section migration. --- .../SourceFiles/info/info_layer_widget.cpp | 41 +++++++++++++++---- Telegram/SourceFiles/info/info_memento.cpp | 2 + Telegram/SourceFiles/window/layer_widget.cpp | 29 +++++++++---- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index c5aea6f2b..52ffc11cd 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -56,12 +56,16 @@ not_null<Window::Controller*> LayerWidget::floatPlayerController() { not_null<Window::AbstractSectionWidget*> LayerWidget::floatPlayerGetSection( Window::Column column) { + Expects(_content != nullptr); + return _content; } void LayerWidget::floatPlayerEnumerateSections(Fn<void( not_null<Window::AbstractSectionWidget*> widget, Window::Column widgetColumn)> callback) { + Expects(_content != nullptr); + callback(_content, Window::Column::Second); } @@ -70,6 +74,8 @@ bool LayerWidget::floatPlayerIsVisible(not_null<HistoryItem*> item) { } void LayerWidget::setupHeightConsumers() { + Expects(_content != nullptr); + _content->scrollTillBottomChanges( ) | rpl::filter([this] { return !_inResize; @@ -90,14 +96,33 @@ void LayerWidget::showFinished() { } void LayerWidget::parentResized() { + if (!_content) { + return; + } + auto parentSize = parentWidget()->size(); auto parentWidth = parentSize.width(); if (parentWidth < MinimalSupportedWidth()) { Ui::FocusPersister persister(this); - auto localCopy = _controller; + restoreFloatPlayerDelegate(); + auto memento = MoveMemento(std::move(_content)); - localCopy->hideSpecialLayer(anim::type::instant); - localCopy->showSection( + + // We want to call hideSpecialLayer synchronously to avoid glitches, + // but we can't destroy LayerStackWidget from its' resizeEvent, + // because QWidget has such code for resizing: + // + // QResizeEvent e(r.size(), olds); + // QApplication::sendEvent(q, &e); + // if (q->windowHandle()) + // q->update(); + // + // So we call it queued. It would be cool to call it 'right after' + // the resize event handling was finished. + InvokeQueued(this, [=] { + _controller->hideSpecialLayer(anim::type::instant); + }); + _controller->showSection( std::move(memento), Window::SectionShow( Window::SectionShow::Way::Forward, @@ -153,7 +178,7 @@ bool LayerWidget::takeToThirdSection() { bool LayerWidget::showSectionInternal( not_null<Window::SectionMemento*> memento, const Window::SectionShow ¶ms) { - if (_content->showInternal(memento, params)) { + if (_content && _content->showInternal(memento, params)) { if (params.activation != anim::activation::background) { Ui::hideLayer(); } @@ -163,11 +188,11 @@ bool LayerWidget::showSectionInternal( } bool LayerWidget::closeByOutsideClick() const { - return _content->closeByOutsideClick(); + return _content ? _content->closeByOutsideClick() : true; } int LayerWidget::MinimalSupportedWidth() { - auto minimalMargins = 2 * st::infoMinimalLayerMargin; + const auto minimalMargins = 2 * st::infoMinimalLayerMargin; return st::infoMinimalWidth + minimalMargins; } @@ -225,7 +250,9 @@ int LayerWidget::resizeGetHeight(int newWidth) { } void LayerWidget::doSetInnerFocus() { - _content->setInnerFocus(); + if (_content) { + _content->setInnerFocus(); + } } void LayerWidget::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 2427fb447..e94a18e8b 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -164,6 +164,8 @@ Memento::~Memento() = default; MoveMemento::MoveMemento(object_ptr<WrapWidget> content) : _content(std::move(content)) { + _content->hide(); + _content->setParent(nullptr); } object_ptr<Window::SectionWidget> MoveMemento::createWidget( diff --git a/Telegram/SourceFiles/window/layer_widget.cpp b/Telegram/SourceFiles/window/layer_widget.cpp index 43a5add9a..73e9fa726 100644 --- a/Telegram/SourceFiles/window/layer_widget.cpp +++ b/Telegram/SourceFiles/window/layer_widget.cpp @@ -497,16 +497,16 @@ void LayerStackWidget::closeLayer(not_null<LayerWidget*> layer) { } void LayerStackWidget::updateLayerBoxes() { - auto getLayerBox = [this]() { - if (auto layer = currentLayer()) { + const auto layerBox = [&] { + if (const auto layer = currentLayer()) { return layer->geometry(); } return QRect(); - }; - auto getSpecialLayerBox = [this]() { - return _specialLayer ? _specialLayer->geometry() : QRect(); - }; - _background->setLayerBoxes(getSpecialLayerBox(), getLayerBox()); + }(); + const auto specialLayerBox = _specialLayer + ? _specialLayer->geometry() + : QRect(); + _background->setLayerBoxes(specialLayerBox, layerBox); update(); } @@ -566,15 +566,28 @@ void LayerStackWidget::startAnimation( } void LayerStackWidget::resizeEvent(QResizeEvent *e) { + const auto weak = make_weak(this); _background->setGeometry(rect()); + if (!weak) { + return; + } if (_specialLayer) { _specialLayer->parentResized(); + if (!weak) { + return; + } } - if (auto layer = currentLayer()) { + if (const auto layer = currentLayer()) { layer->parentResized(); + if (!weak) { + return; + } } if (_mainMenu) { _mainMenu->resize(_mainMenu->width(), height()); + if (!weak) { + return; + } } updateLayerBoxes(); }