diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index a051e8aab..bfb703c2b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -744,15 +744,15 @@ void Widget::changeOpenedSubsection( if (isHidden()) { animated = anim::type::instant; } - auto cacheUnder = QPixmap(); + auto oldContentCache = QPixmap(); const auto showDirection = fromRight ? Window::SlideDirection::FromRight : Window::SlideDirection::FromLeft; if (animated == anim::type::normal) { _connecting->setForceHidden(true); - cacheUnder = grabForFolderSlideAnimation(); + oldContentCache = grabForFolderSlideAnimation(); } - _a_show.stop(); + _showAnimation = nullptr; change(); refreshTopBars(); updateControlsVisibility(true); @@ -760,9 +760,12 @@ void Widget::changeOpenedSubsection( _api.request(base::take(_topicSearchRequest)).cancel(); if (animated == anim::type::normal) { _connecting->setForceHidden(true); - auto cacheOver = grabForFolderSlideAnimation(); + auto newContentCache = grabForFolderSlideAnimation(); _connecting->setForceHidden(false); - startSlideAnimation(); + startSlideAnimation( + std::move(oldContentCache), + std::move(newContentCache), + showDirection); } } @@ -872,7 +875,7 @@ void Widget::refreshTopBars() { } }, _forumGroupCallBar->lifetime()); - if (_a_show.animating()) { + if (_showAnimation) { _forumTopShadow->hide(); _forumGroupCallBar->hide(); _forumRequestsBar->hide(); @@ -1048,7 +1051,7 @@ void Widget::startWidthAnimation() { void Widget::stopWidthAnimation() { _widthAnimationCache = QPixmap(); - if (!_a_show.animating()) { + if (!_showAnimation) { _scroll->show(); } update(); @@ -1062,21 +1065,27 @@ void Widget::showFast() { } void Widget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) { - _showDirection = direction; - _a_show.stop(); + _showAnimation = nullptr; - _cacheUnder = params.oldContentCache; + auto oldContentCache = params.oldContentCache; showFast(); - _cacheOver = controller()->content()->grabForShowAnimation(params); + const auto content = controller()->content(); + auto newContentCache = content->grabForShowAnimation(params); if (_updateTelegram) { _updateTelegram->hide(); } _connecting->setForceHidden(true); - startSlideAnimation(); + startSlideAnimation( + std::move(oldContentCache), + std::move(newContentCache), + direction); } -void Widget::startSlideAnimation() { +void Widget::startSlideAnimation( + QPixmap oldContentCache, + QPixmap newContentCache, + Window::SlideDirection direction) { _scroll->hide(); _searchControls->hide(); if (_subsectionTopBar) { @@ -1095,10 +1104,12 @@ void Widget::startSlideAnimation() { _forumReportBar->bar().hide(); } - if (_showDirection == Window::SlideDirection::FromLeft) { - std::swap(_cacheUnder, _cacheOver); - } - _a_show.start([=] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); + _showAnimation = std::make_unique(); + _showAnimation->setDirection(direction); + _showAnimation->setRepaintCallback([=] { update(); }); + _showAnimation->setFinishedCallback([=] { slideFinished(); }); + _showAnimation->setPixmaps(oldContentCache, newContentCache); + _showAnimation->start(); } bool Widget::floatPlayerHandleWheelEvent(QEvent *e) { @@ -1109,17 +1120,12 @@ QRect Widget::floatPlayerAvailableRect() { return mapToGlobal(_scroll->geometry()); } -void Widget::animationCallback() { - update(); - if (!_a_show.animating()) { - _cacheUnder = _cacheOver = QPixmap(); - - updateControlsVisibility(true); - - if ((!_subsectionTopBar || !_subsectionTopBar->searchHasFocus()) - && !_filter->hasFocus()) { - controller()->widget()->setInnerFocus(); - } +void Widget::slideFinished() { + _showAnimation = nullptr; + updateControlsVisibility(true); + if ((!_subsectionTopBar || !_subsectionTopBar->searchHasFocus()) + && !_filter->hasFocus()) { + controller()->widget()->setInnerFocus(); } } @@ -1854,7 +1860,7 @@ void Widget::listScrollUpdated() { } void Widget::applyFilterUpdate(bool force) { - if (_a_show.animating() && !force) { + if (_showAnimation && !force) { return; } @@ -2099,7 +2105,7 @@ void Widget::resizeEvent(QResizeEvent *e) { } void Widget::updateLockUnlockVisibility() { - if (_a_show.animating()) { + if (_showAnimation) { return; } const auto hidden = !session().domain().local().hasLocalPasscode(); @@ -2110,7 +2116,7 @@ void Widget::updateLockUnlockVisibility() { } void Widget::updateLoadMoreChatsVisibility() { - if (_a_show.animating() || !_loadMoreChats) { + if (_showAnimation || !_loadMoreChats) { return; } const auto hidden = (_openedFolder != nullptr) @@ -2123,7 +2129,9 @@ void Widget::updateLoadMoreChatsVisibility() { } void Widget::updateJumpToDateVisibility(bool fast) { - if (_a_show.animating()) return; + if (_showAnimation) { + return; + } _jumpToDate->toggle( (_searchInChat && _filter->getLastText().isEmpty()), @@ -2306,24 +2314,8 @@ void Widget::paintEvent(QPaintEvent *e) { if (r != rect()) { p.setClipRect(r); } - if (_a_show.animating()) { - const auto progress = _a_show.value(1.); - const auto top = 0; - const auto shift = std::min(st::slideShift, width() / 2); - const auto retina = cIntRetinaFactor(); - const auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); - const auto coordUnder = fromLeft ? anim::interpolate(-shift, 0, progress) : anim::interpolate(0, -shift, progress); - const auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - const auto shadow = fromLeft ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, top, coordOver, _cacheUnder.height() / retina), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, _cacheUnder.height())); - p.setOpacity(shadow); - p.fillRect(0, top, coordOver, _cacheUnder.height() / retina, st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(QRect(coordOver, top, _cacheOver.width() / retina, _cacheOver.height() / retina), _cacheOver, QRect(0, 0, _cacheOver.width(), _cacheOver.height())); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), top, st::slideShadow.width(), _cacheOver.height() / retina)); + if (_showAnimation) { + _showAnimation->paintContents(p); return; } auto above = QRect(0, 0, width(), _scroll->y()); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index b914d747e..9461296dc 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -139,7 +139,7 @@ private: bool searchMessages(bool searchCache = false); void needSearchMessages(); - void animationCallback(); + void slideFinished(); void searchReceived( SearchRequestType type, const MTPmessages_Messages &result, @@ -182,7 +182,10 @@ private: void changeOpenedForum(Data::Forum *forum, anim::type animated); void hideChildList(); [[nodiscard]] QPixmap grabForFolderSlideAnimation(); - void startSlideAnimation(); + void startSlideAnimation( + QPixmap oldContentCache, + QPixmap newContentCache, + Window::SlideDirection direction); void fullSearchRefreshOn(rpl::producer<> events); void applyFilterUpdate(bool force = false); @@ -233,9 +236,7 @@ private: std::unique_ptr _connecting; Ui::Animations::Simple _scrollToAnimation; - Ui::Animations::Simple _a_show; - Window::SlideDirection _showDirection = Window::SlideDirection(); - QPixmap _cacheUnder, _cacheOver; + std::unique_ptr _showAnimation; Ui::Animations::Simple _scrollToTopShown; object_ptr _scrollToTop; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index b4fc56fe3..5136e58fe 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -803,7 +803,7 @@ HistoryWidget::HistoryWidget( session().data().itemVisibilityQueries( ) | rpl::filter([=]( const Data::Session::ItemVisibilityQuery &query) { - return !_a_show.animating() + return !_showAnimation && (_history == query.item->history()) && (query.item->mainView() != nullptr) && isVisible(); @@ -2620,13 +2620,13 @@ std::optional HistoryWidget::writeRestriction() const { } void HistoryWidget::updateControlsVisibility() { - if (!_a_show.animating()) { + if (!_showAnimation) { _topShadow->setVisible(_peer != nullptr); _topBar->setVisible(_peer != nullptr); } _cornerButtons.updateJumpDownVisibility(); _cornerButtons.updateUnreadThingsVisibility(); - if (!_history || _a_show.animating()) { + if (!_history || _showAnimation) { hideChildWidgets(); return; } @@ -3161,7 +3161,7 @@ bool HistoryWidget::markingContentsRead() const { && _historyInited && !_firstLoadRequest && !_delayedShowAtRequest - && !_a_show.animating() + && !_showAnimation && controller()->widget()->markingAsRead(); } @@ -3940,11 +3940,7 @@ MsgId HistoryWidget::msgId() const { void HistoryWidget::showAnimated( Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) { - _showDirection = direction; - - _a_show.stop(); - - _cacheUnder = params.oldContentCache; + _showAnimation = nullptr; // If we show pinned bar here, we don't want it to change the // calculated and prepared scrollTop of the messages history. @@ -3965,40 +3961,40 @@ void HistoryWidget::showAnimated( _preserveScrollTop = false; _stickerToast = nullptr; - _cacheOver = controller()->content()->grabForShowAnimation(params); + auto newContentCache = Ui::GrabWidget(this); hideChildWidgets(); if (params.withTopBarShadow) _topShadow->show(); - if (_showDirection == Window::SlideDirection::FromLeft) { - std::swap(_cacheUnder, _cacheOver); - } - _a_show.start([=] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); if (_history) { _topBar->show(); _topBar->setAnimatingMode(true); } + _showAnimation = std::make_unique(); + _showAnimation->setDirection(direction); + _showAnimation->setRepaintCallback([=] { update(); }); + _showAnimation->setFinishedCallback([=] { showFinished(); }); + _showAnimation->setPixmaps(params.oldContentCache, newContentCache); + _showAnimation->start(); + activate(); } -void HistoryWidget::animationCallback() { - update(); - if (!_a_show.animating()) { - _cornerButtons.finishAnimations(); - if (_pinnedBar) { - _pinnedBar->finishAnimating(); - } - if (_groupCallBar) { - _groupCallBar->finishAnimating(); - } - if (_requestsBar) { - _requestsBar->finishAnimating(); - } - _cacheUnder = _cacheOver = QPixmap(); - doneShow(); - synteticScrollToY(_scroll->scrollTop()); +void HistoryWidget::showFinished() { + _cornerButtons.finishAnimations(); + if (_pinnedBar) { + _pinnedBar->finishAnimating(); } + if (_groupCallBar) { + _groupCallBar->finishAnimating(); + } + if (_requestsBar) { + _requestsBar->finishAnimating(); + } + _showAnimation = nullptr; + doneShow(); + synteticScrollToY(_scroll->scrollTop()); } void HistoryWidget::doneShow() { @@ -4083,10 +4079,10 @@ void HistoryWidget::checkSuggestToGigagroup() { } void HistoryWidget::finishAnimating() { - if (!_a_show.animating()) { + if (!_showAnimation) { return; } - _a_show.stop(); + _showAnimation = nullptr; _topShadow->setVisible(_peer != nullptr); _topBar->setVisible(_peer != nullptr); _cornerButtons.finishAnimations(); @@ -4549,7 +4545,7 @@ bool HistoryWidget::kbWasHidden() const { } void HistoryWidget::toggleKeyboard(bool manual) { - auto fieldEnabled = canWriteMessage() && !_a_show.animating(); + auto fieldEnabled = canWriteMessage() && !_showAnimation; if (_kbShown || _kbReplyTo) { _botKeyboardHide->hide(); if (_kbShown) { @@ -4621,7 +4617,7 @@ void HistoryWidget::toggleKeyboard(bool manual) { } updateControlsGeometry(); updateFieldPlaceholder(); - if (_botKeyboardHide->isHidden() && canWriteMessage() && !_a_show.animating()) { + if (_botKeyboardHide->isHidden() && canWriteMessage() && !_showAnimation) { _tabbedSelectorToggle->show(); } else { _tabbedSelectorToggle->hide(); @@ -4882,7 +4878,7 @@ void HistoryWidget::fieldFocused() { } void HistoryWidget::checkFieldAutocomplete() { - if (!_history || _a_show.animating()) { + if (!_history || _showAnimation) { return; } @@ -5441,7 +5437,7 @@ void HistoryWidget::updateHistoryGeometry( if (!_history || (initial && _historyInited) || (!initial && !_historyInited)) { return; } - if (_firstLoadRequest || _a_show.animating()) { + if (_firstLoadRequest || _showAnimation) { _updateHistoryGeometryRequired = true; return; // scrollTopMax etc are not working after recountHistoryGeometry() } @@ -5742,7 +5738,7 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) { _history->lastKeyboardHiddenId = _history->lastKeyboardId; } if (!isSearching() && !isBotStart() && !isBlocked() && _canSendMessages && (wasVisible || (_replyToId && _replyEditMsg) || (!HasSendText(_field) && !kbWasHidden()))) { - if (!_a_show.animating()) { + if (!_showAnimation) { if (hasMarkup) { _kbScroll->show(); _tabbedSelectorToggle->hide(); @@ -5767,7 +5763,7 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) { updateReplyEditText(_kbReplyTo); } } else { - if (!_a_show.animating()) { + if (!_showAnimation) { _kbScroll->hide(); _tabbedSelectorToggle->show(); _botKeyboardHide->hide(); @@ -5847,7 +5843,7 @@ int HistoryWidget::computeMaxFieldHeight() const { } bool HistoryWidget::cornerButtonsIgnoreVisibility() { - return _a_show.animating(); + return _showAnimation != nullptr; } std::optional HistoryWidget::cornerButtonsDownShown() { @@ -6302,7 +6298,7 @@ void HistoryWidget::checkPinnedBarState() { orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _pinnedBar->hide(); } } @@ -6478,7 +6474,7 @@ void HistoryWidget::setupGroupCallBar() { orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _groupCallBar->hide(); } } @@ -6525,7 +6521,7 @@ void HistoryWidget::setupRequestsBar() { orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _requestsBar->hide(); } } @@ -7193,7 +7189,7 @@ void HistoryWidget::handlePeerUpdate() { session().api().chatParticipants().requestAdmins(channel); } } - if (!_a_show.animating()) { + if (!_showAnimation) { if (_unblock->isHidden() == isBlocked() || (!isBlocked() && _joinChannel->isHidden() == isJoinChannel())) { resize = true; @@ -7637,28 +7633,12 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int } bool HistoryWidget::paintShowAnimationFrame() { - auto progress = _a_show.value(1.); - if (!_a_show.animating()) { - return false; + if (_showAnimation) { + QPainter p(this); + _showAnimation->paintContents(p); + return true; } - - Painter p(this); - auto animationWidth = width(); - auto retina = cIntRetinaFactor(); - auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); - auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = fromLeft ? anim::interpolate(0, animationWidth, progress) : anim::interpolate(animationWidth, 0, progress); - auto shadow = fromLeft ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, height() * retina)); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, 0, _cacheOver.width(), height() * retina)); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); - return true; + return false; } void HistoryWidget::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index bda30bfec..1dea2549e 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -162,7 +162,9 @@ public: bool hasTopBarShadow() const { return peer() != nullptr; } - void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms); + void showAnimated( + Window::SlideDirection direction, + const Window::SectionSlideParams ¶ms); void finishAnimating(); void doneShow(); @@ -403,7 +405,7 @@ private: auto computeSendButtonType() const; - void animationCallback(); + void showFinished(); void updateOverStates(QPoint pos); void chooseAttach(std::optional overrideSendImagesAsPhotos = {}); void sendButtonClicked(); @@ -754,9 +756,7 @@ private: QString _confirmSource; - Ui::Animations::Simple _a_show; - Window::SlideDirection _showDirection; - QPixmap _cacheUnder, _cacheOver; + std::unique_ptr _showAnimation; HistoryView::ElementHighlighter _highlighter; diff --git a/Telegram/SourceFiles/intro/intro_widget.cpp b/Telegram/SourceFiles/intro/intro_widget.cpp index f9b6c0753..89fa20aee 100644 --- a/Telegram/SourceFiles/intro/intro_widget.cpp +++ b/Telegram/SourceFiles/intro/intro_widget.cpp @@ -297,7 +297,7 @@ void Widget::checkUpdateStatus() { this, tr::lng_menu_update(), st::defaultBoxButton)); - if (!_a_show.animating()) { + if (!_showAnimation) { _update->setVisible(true); } const auto stepHasCover = getStep()->hasCover(); @@ -699,62 +699,47 @@ void Widget::hideControls() { _back->hide(anim::type::instant); } -void Widget::showAnimated(const QPixmap &bgAnimCache, bool back) { - _showBack = back; +void Widget::showAnimated(QPixmap oldContentCache, bool back) { + _showAnimation = nullptr; - (_showBack ? _cacheOver : _cacheUnder) = bgAnimCache; - - _a_show.stop(); showControls(); floatPlayerHideAll(); - (_showBack ? _cacheUnder : _cacheOver) = Ui::GrabWidget(this); + auto newContentCache = Ui::GrabWidget(this); hideControls(); floatPlayerShowVisible(); - _a_show.start( - [=] { animationCallback(); }, - 0., - 1., - st::slideDuration, - Window::SlideAnimation::transition()); + _showAnimation = std::make_unique(); + _showAnimation->setDirection(back + ? Window::SlideDirection::FromLeft + : Window::SlideDirection::FromRight); + _showAnimation->setRepaintCallback([=] { update(); }); + _showAnimation->setFinishedCallback([=] { showFinished(); }); + _showAnimation->setPixmaps(oldContentCache, newContentCache); + _showAnimation->start(); show(); } -void Widget::animationCallback() { - update(); - if (!_a_show.animating()) { - _cacheUnder = _cacheOver = QPixmap(); +void Widget::showFinished() { + _showAnimation = nullptr; - showControls(); - getStep()->activate(); - } + showControls(); + getStep()->activate(); } void Widget::paintEvent(QPaintEvent *e) { - bool trivial = (rect() == e->rect()); + const auto trivial = (rect() == e->rect()); setMouseTracking(true); QPainter p(this); if (!trivial) { p.setClipRect(e->rect()); } - p.fillRect(e->rect(), st::windowBg); - auto progress = _a_show.value(1.); - if (_a_show.animating()) { - auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - auto shadow = _showBack ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor())); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(coordOver, 0, _cacheOver); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); + if (_showAnimation) { + _showAnimation->paintContents(p); + return; } + p.fillRect(e->rect(), st::windowBg); } void Widget::resizeEvent(QResizeEvent *e) { @@ -803,7 +788,7 @@ void Widget::updateControlsGeometry() { } void Widget::keyPressEvent(QKeyEvent *e) { - if (_a_show.animating() || getStep()->animating()) return; + if (_showAnimation || getStep()->animating()) return; if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { if (getStep()->hasBack()) { diff --git a/Telegram/SourceFiles/intro/intro_widget.h b/Telegram/SourceFiles/intro/intro_widget.h index 96882b15f..e40d914c9 100644 --- a/Telegram/SourceFiles/intro/intro_widget.h +++ b/Telegram/SourceFiles/intro/intro_widget.h @@ -30,6 +30,7 @@ class FadeWrap; namespace Window { class ConnectionState; class Controller; +class SlideAnimation; } // namespace Window namespace Intro { @@ -96,15 +97,14 @@ public: not_null controller, not_null account, EnterPoint point); + ~Widget(); - void showAnimated(const QPixmap &bgAnimCache, bool back = false); + void showAnimated(QPixmap oldContentCache, bool back = false); void setInnerFocus(); [[nodiscard]] rpl::producer<> showSettingsRequested() const; - ~Widget(); - protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; @@ -112,7 +112,7 @@ protected: private: void refreshLang(); - void animationCallback(); + void showFinished(); void createLanguageLink(); void checkUpdateStatus(); void setupNextButton(); @@ -175,9 +175,7 @@ private: std::optional _api; mtpRequestId _nearestDcRequestId = 0; - Ui::Animations::Simple _a_show; - bool _showBack = false; - QPixmap _cacheUnder, _cacheOver; + std::unique_ptr _showAnimation; std::vector _stepHistory; rpl::lifetime _stepLifetime; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 994089b4e..3f7f2041d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -816,7 +816,7 @@ void MainWidget::createPlayer() { }, _player->lifetime()); orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _player->show(anim::type::instant); _player->setVisible(false); Shortcuts::ToggleMediaShortcuts(true); @@ -825,7 +825,7 @@ void MainWidget::createPlayer() { } } if (_player && !_player->toggled()) { - if (!_a_show.animating()) { + if (!_showAnimation) { _player->show(anim::type::normal); _playerHeight = _contentScrollAddToY = _player->contentHeight(); updateControlsGeometry(); @@ -916,7 +916,7 @@ void MainWidget::createCallTopBar() { callTopBarHeightUpdated(value); }, lifetime()); orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _callTopBar->show(anim::type::instant); _callTopBar->setVisible(false); } else { @@ -980,7 +980,7 @@ void MainWidget::createExportTopBar(Export::View::Content &&data) { } }, _exportTopBar->lifetime()); orderWidgets(); - if (_a_show.animating()) { + if (_showAnimation) { _exportTopBar->show(anim::type::instant); _exportTopBar->setVisible(false); } else { @@ -1318,7 +1318,7 @@ void MainWidget::showPeerHistory( } auto animatedShow = [&] { - if (_a_show.animating() + if (_showAnimation || Core::App().passcodeLocked() || (params.animated == anim::type::instant)) { return false; @@ -1369,7 +1369,7 @@ void MainWidget::showPeerHistory( if (onlyDialogs) { Assert(_dialogs != nullptr); _history->hide(); - if (!_a_show.animating()) { + if (!_showAnimation) { if (animationParams) { auto direction = back ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight; _dialogs->showAnimated(direction, animationParams); @@ -1385,7 +1385,7 @@ void MainWidget::showPeerHistory( if (isOneColumn() && _dialogs && !_dialogs->isHidden()) { _dialogs->hide(); } - if (!_a_show.animating()) { + if (!_showAnimation) { if (!animationParams.oldContentCache.isNull()) { _history->showAnimated( back @@ -1661,7 +1661,7 @@ void MainWidget::showNewSection( Assert(newMainSection || newThirdSection); auto animatedShow = [&] { - if (_a_show.animating() + if (_showAnimation || Core::App().passcodeLocked() || (params.animated == anim::type::instant) || memento->instant()) { @@ -1965,58 +1965,41 @@ void MainWidget::checkActivation() { } } -void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) { - _showBack = back; - (_showBack ? _cacheOver : _cacheUnder) = bgAnimCache; - - _a_show.stop(); +void MainWidget::showAnimated(QPixmap oldContentCache, bool back) { + _showAnimation = nullptr; showAll(); floatPlayerHideAll(); - (_showBack ? _cacheUnder : _cacheOver) = Ui::GrabWidget(this); + auto newContentCache = Ui::GrabWidget(this); hideAll(); floatPlayerShowVisible(); - _a_show.start( - [this] { animationCallback(); }, - 0., - 1., - st::slideDuration, - Window::SlideAnimation::transition()); + _showAnimation = std::make_unique(); + _showAnimation->setDirection(back + ? Window::SlideDirection::FromLeft + : Window::SlideDirection::FromRight); + _showAnimation->setRepaintCallback([=] { update(); }); + _showAnimation->setFinishedCallback([=] { showFinished(); }); + _showAnimation->setPixmaps(oldContentCache, newContentCache); + _showAnimation->start(); show(); } -void MainWidget::animationCallback() { - update(); - if (!_a_show.animating()) { - _cacheUnder = _cacheOver = QPixmap(); +void MainWidget::showFinished() { + _showAnimation = nullptr; - showAll(); - activate(); - } + showAll(); + activate(); } void MainWidget::paintEvent(QPaintEvent *e) { if (_background) { checkChatBackground(); } - - auto p = QPainter(this); - auto progress = _a_show.value(1.); - if (_a_show.animating()) { - auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - auto shadow = _showBack ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor())); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(coordOver, 0, _cacheOver); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); + if (_showAnimation) { + auto p = QPainter(this); + _showAnimation->paintContents(p); } } @@ -2653,7 +2636,7 @@ bool MainWidget::contentOverlapped(const QRect &globalRect) { } void MainWidget::activate() { - if (_a_show.animating()) { + if (_showAnimation) { return; } else if (const auto paths = cSendPaths(); !paths.isEmpty()) { const auto interpret = u"interpret://"_q; @@ -2688,7 +2671,7 @@ void MainWidget::activate() { } bool MainWidget::animatingShow() const { - return _a_show.animating(); + return _showAnimation != nullptr; } bool MainWidget::isOneColumn() const { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 88fe8937a..a38172a69 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -89,6 +89,7 @@ class TopBarWrapWidget; class SectionMemento; class SectionWidget; class AbstractSectionWidget; +class SlideAnimation; class ConnectionState; struct SectionSlideParams; struct SectionShow; @@ -137,7 +138,7 @@ public: void returnTabbedSelector(); - void showAnimated(const QPixmap &bgAnimCache, bool back = false); + void showAnimated(QPixmap oldContentCache, bool back = false); void activate(); @@ -248,7 +249,7 @@ protected: bool eventFilter(QObject *o, QEvent *e) override; private: - void animationCallback(); + void showFinished(); void handleAdaptiveLayoutUpdate(); void updateWindowAdaptiveLayout(); void handleAudioUpdate(const Media::Player::TrackState &state); @@ -342,9 +343,7 @@ private: const not_null _controller; - Ui::Animations::Simple _a_show; - bool _showBack = false; - QPixmap _cacheUnder, _cacheOver; + std::unique_ptr _showAnimation; int _dialogsWidth = 0; int _thirdColumnWidth = 0; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index b74246506..9f4a94504 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -172,15 +172,8 @@ void MainWindow::clearWidgetsHook() { } } -QPixmap MainWindow::grabInner() { - if (_passcodeLock) { - return Ui::GrabWidget(_passcodeLock); - } else if (_intro) { - return Ui::GrabWidget(_intro); - } else if (_main) { - return Ui::GrabWidget(_main); - } - return {}; +QPixmap MainWindow::grabForSlideAnimation() { + return Ui::GrabWidget(bodyWidget()); } void MainWindow::preventOrInvoke(Fn callback) { @@ -192,7 +185,7 @@ void MainWindow::preventOrInvoke(Fn callback) { void MainWindow::setupPasscodeLock() { auto animated = (_main || _intro); - auto bg = animated ? grabInner() : QPixmap(); + auto oldContentCache = animated ? grabForSlideAnimation() : QPixmap(); _passcodeLock.create(bodyWidget(), &controller()); updateControlsGeometry(); @@ -205,7 +198,7 @@ void MainWindow::setupPasscodeLock() { _intro->hide(); } if (animated) { - _passcodeLock->showAnimated(bg); + _passcodeLock->showAnimated(std::move(oldContentCache)); } else { _passcodeLock->showFinished(); setInnerFocus(); @@ -213,29 +206,30 @@ void MainWindow::setupPasscodeLock() { } void MainWindow::clearPasscodeLock() { + Expects(_intro || _main); + if (!_passcodeLock) { return; } + auto oldContentCache = grabForSlideAnimation(); + _passcodeLock.destroy(); if (_intro) { - auto bg = grabInner(); - _passcodeLock.destroy(); _intro->show(); updateControlsGeometry(); - _intro->showAnimated(bg, true); + _intro->showAnimated(std::move(oldContentCache), true); } else if (_main) { - auto bg = grabInner(); - _passcodeLock.destroy(); _main->show(); updateControlsGeometry(); - _main->showAnimated(bg, true); + _main->showAnimated(std::move(oldContentCache), true); Core::App().checkStartUrl(); } } -void MainWindow::setupIntro(Intro::EnterPoint point) { +void MainWindow::setupIntro( + Intro::EnterPoint point, + QPixmap oldContentCache) { auto animated = (_main || _passcodeLock); - auto bg = animated ? grabInner() : QPixmap(); destroyLayer(); auto created = object_ptr( @@ -256,7 +250,7 @@ void MainWindow::setupIntro(Intro::EnterPoint point) { _intro->show(); updateControlsGeometry(); if (animated) { - _intro->showAnimated(bg); + _intro->showAnimated(std::move(oldContentCache)); } else { setInnerFocus(); } @@ -264,12 +258,13 @@ void MainWindow::setupIntro(Intro::EnterPoint point) { fixOrder(); } -void MainWindow::setupMain(MsgId singlePeerShowAtMsgId) { +void MainWindow::setupMain( + MsgId singlePeerShowAtMsgId, + QPixmap oldContentCache) { Expects(account().sessionExists()); const auto animated = _intro || (_passcodeLock && !Core::App().passcodeLocked()); - const auto bg = animated ? grabInner() : QPixmap(); const auto weakAnimatedLayer = (_main && _layer && !_passcodeLock) ? Ui::MakeWeak(_layer.get()) : nullptr; @@ -295,7 +290,7 @@ void MainWindow::setupMain(MsgId singlePeerShowAtMsgId) { _main->show(); updateControlsGeometry(); if (animated) { - _main->showAnimated(bg); + _main->showAnimated(std::move(oldContentCache)); } else { _main->activate(); } diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 1fdb30349..66cf9ec1c 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -53,8 +53,8 @@ public: void setupPasscodeLock(); void clearPasscodeLock(); - void setupIntro(Intro::EnterPoint point); - void setupMain(MsgId singlePeerShowAtMsgId); + void setupIntro(Intro::EnterPoint point, QPixmap oldContentCache); + void setupMain(MsgId singlePeerShowAtMsgId, QPixmap oldContentCache); void showSettings(); @@ -83,6 +83,8 @@ public: void showMainMenu(); void fixOrder() override; + [[nodiscard]] QPixmap grabForSlideAnimation(); + void showLayer( std::unique_ptr &&layer, Ui::LayerOptions options, @@ -132,8 +134,6 @@ private: void themeUpdated(const Window::Theme::BackgroundUpdate &data); - QPixmap grabInner(); - std::unique_ptr _mediaControlsManager; QPoint _lastMousePosition; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 62c12e8dc..1557f8a3d 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -103,10 +103,11 @@ void Controller::showAccount( _sessionController = session ? std::make_unique(session, this) : nullptr; - setupSideBar(); + auto oldContentCache = _widget.grabForSlideAnimation(); _widget.updateWindowIcon(); if (session) { - setupMain(singlePeerShowAtMsgId); + setupSideBar(); + setupMain(singlePeerShowAtMsgId, std::move(oldContentCache)); session->updates().isIdleValue( ) | rpl::filter([=](bool idle) { @@ -125,7 +126,8 @@ void Controller::showAccount( session->updates().updateOnline(crl::now()); } else { - setupIntro(); + sideBarChanged(); + setupIntro(std::move(oldContentCache)); _widget.updateGlobalMenu(); } @@ -138,13 +140,11 @@ PeerData *Controller::singlePeer() const { } void Controller::setupSideBar() { + Expects(_sessionController != nullptr); + if (!isPrimary()) { return; } - if (!_sessionController) { - sideBarChanged(); - return; - } _sessionController->filtersMenuChanged( ) | rpl::start_with_next([=] { sideBarChanged(); @@ -283,16 +283,19 @@ void Controller::clearPasscodeLock() { } } -void Controller::setupIntro() { - _widget.setupIntro(Core::App().domain().maybeLastOrSomeAuthedAccount() +void Controller::setupIntro(QPixmap oldContentCache) { + const auto point = Core::App().domain().maybeLastOrSomeAuthedAccount() ? Intro::EnterPoint::Qr - : Intro::EnterPoint::Start); + : Intro::EnterPoint::Start; + _widget.setupIntro(point, std::move(oldContentCache)); } -void Controller::setupMain(MsgId singlePeerShowAtMsgId) { +void Controller::setupMain( + MsgId singlePeerShowAtMsgId, + QPixmap oldContentCache) { Expects(_sessionController != nullptr); - _widget.setupMain(singlePeerShowAtMsgId); + _widget.setupMain(singlePeerShowAtMsgId, std::move(oldContentCache)); if (const auto id = Ui::Emoji::NeedToSwitchBackToId()) { Ui::Emoji::LoadAndSwitchTo(&_sessionController->session(), id); diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index c8a850ff3..076442b49 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -62,8 +62,6 @@ public: void setupPasscodeLock(); void clearPasscodeLock(); - void setupIntro(); - void setupMain(MsgId singlePeerShowAtMsgId); void showLogoutConfirmation(); @@ -121,6 +119,9 @@ private: }; explicit Controller(CreateArgs &&args); + void setupIntro(QPixmap oldContentCache); + void setupMain(MsgId singlePeerShowAtMsgId, QPixmap oldContentCache); + void showAccount( not_null account, MsgId singlePeerShowAtMsgId); diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index c58c05127..0e6278549 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -34,6 +34,8 @@ LockWidget::LockWidget(QWidget *parent, not_null window) show(); } +LockWidget::~LockWidget() = default; + not_null LockWidget::window() const { return _window; } @@ -45,62 +47,40 @@ void LockWidget::setInnerFocus() { setFocus(); } -void LockWidget::showAnimated(const QPixmap &bgAnimCache, bool back) { - _showBack = back; - (_showBack ? _cacheOver : _cacheUnder) = bgAnimCache; - - _a_show.stop(); +void LockWidget::showAnimated(QPixmap oldContentCache) { + _showAnimation = nullptr; showChildren(); setInnerFocus(); - (_showBack ? _cacheUnder : _cacheOver) = Ui::GrabWidget(this); + auto newContentCache = Ui::GrabWidget(this); hideChildren(); - _a_show.start( - [this] { animationCallback(); }, - 0., - 1., - st::slideDuration, - Window::SlideAnimation::transition()); - show(); -} + _showAnimation = std::make_unique(); + _showAnimation->setRepaintCallback([=] { update(); }); + _showAnimation->setFinishedCallback([=] { showFinished(); }); + _showAnimation->setPixmaps(oldContentCache, newContentCache); + _showAnimation->start(); -void LockWidget::animationCallback() { - update(); - if (!_a_show.animating()) { - showFinished(); - } + show(); } void LockWidget::showFinished() { showChildren(); _window->widget()->setInnerFocus(); + _showAnimation = nullptr; if (const auto controller = _window->sessionController()) { controller->clearSectionStack(); } - _cacheUnder = _cacheOver = QPixmap(); } void LockWidget::paintEvent(QPaintEvent *e) { auto p = QPainter(this); - auto progress = _a_show.value(1.); - if (_a_show.animating()) { - auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - auto shadow = _showBack ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor())); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(coordOver, 0, _cacheOver); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); - } else { - paintContent(p); + if (_showAnimation) { + _showAnimation->paintContents(p); + return; } + paintContent(p); } void LockWidget::paintContent(QPainter &p) { diff --git a/Telegram/SourceFiles/window/window_lock_widgets.h b/Telegram/SourceFiles/window/window_lock_widgets.h index d21bc585c..b55d0042d 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.h +++ b/Telegram/SourceFiles/window/window_lock_widgets.h @@ -26,16 +26,18 @@ class Session; namespace Window { class Controller; +class SlideAnimation; class LockWidget : public Ui::RpWidget { public: LockWidget(QWidget *parent, not_null window); + ~LockWidget(); - not_null window() const; + [[nodiscard]] not_null window() const; virtual void setInnerFocus(); - void showAnimated(const QPixmap &bgAnimCache, bool back = false); + void showAnimated(QPixmap oldContentCache); void showFinished(); protected: @@ -43,12 +45,8 @@ protected: virtual void paintContent(QPainter &p); private: - void animationCallback(); - const not_null _window; - Ui::Animations::Simple _a_show; - bool _showBack = false; - QPixmap _cacheUnder, _cacheOver; + std::unique_ptr _showAnimation; };