From ffd65e1fe45e77aa73eab6c2f9b795f25554fbef Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 23 Feb 2022 13:53:27 +0300 Subject: [PATCH] Fix slide animations with new layer rounding. --- .../admin_log/history_admin_log_section.cpp | 5 +-- .../view/history_view_pinned_section.cpp | 4 +- .../view/history_view_replies_section.cpp | 42 +++++++++---------- .../view/history_view_scheduled_section.cpp | 7 ++-- .../SourceFiles/info/info_layer_widget.cpp | 15 ++++--- .../SourceFiles/info/info_wrap_widget.cpp | 5 ++- .../SourceFiles/settings/settings_intro.cpp | 18 ++++---- .../SourceFiles/window/section_widget.cpp | 7 +++- Telegram/SourceFiles/window/section_widget.h | 6 +-- .../window/window_slide_animation.cpp | 14 ++++--- .../window/window_slide_animation.h | 4 +- 11 files changed, 67 insertions(+), 60 deletions(-) diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp index 56adbaff2..b8c9e76dc 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp @@ -458,11 +458,10 @@ void Widget::resizeEvent(QResizeEvent *e) { } void Widget::paintEvent(QPaintEvent *e) { - if (animating()) { + if (animatingShow()) { SectionWidget::paintEvent(e); return; - } - if (Ui::skipPaintEvent(this, e)) { + } else if (Ui::skipPaintEvent(this, e)) { return; } //if (hasPendingResizedItems()) { diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index 901b6944c..38b69af64 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -270,7 +270,7 @@ bool PinnedWidget::showAtPositionNow( } void PinnedWidget::updateScrollDownVisibility() { - if (animating()) { + if (animatingShow()) { return; } @@ -467,7 +467,7 @@ void PinnedWidget::updateControlsGeometry() { } void PinnedWidget::paintEvent(QPaintEvent *e) { - if (animating()) { + if (animatingShow()) { SectionWidget::paintEvent(e); return; } else if (Ui::skipPaintEvent(this, e)) { diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index a6428e7e9..c98da84ec 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -1344,7 +1344,7 @@ bool RepliesWidget::showAtPositionNow( } void RepliesWidget::updateScrollDownVisibility() { - if (animating()) { + if (animatingShow()) { return; } @@ -1617,7 +1617,7 @@ void RepliesWidget::updateControlsGeometry() { } void RepliesWidget::paintEvent(QPaintEvent *e) { - if (animating()) { + if (animatingShow()) { SectionWidget::paintEvent(e); return; } else if (Ui::skipPaintEvent(this, e)) { @@ -1667,28 +1667,28 @@ void RepliesWidget::updatePinnedVisibility() { } void RepliesWidget::setPinnedVisibility(bool shown) { - if (!animating()) { - if (!_rootViewInited) { - const auto height = shown ? st::historyReplyHeight : 0; - if (const auto delta = height - _rootViewHeight) { - _rootViewHeight = height; - if (_scroll->scrollTop() == _scroll->scrollTopMax()) { - setGeometryWithTopMoved(geometry(), delta); - } else { - updateControlsGeometry(); - } - } - if (shown) { - _rootView->show(); + if (animatingShow()) { + return; + } else if (!_rootViewInited) { + const auto height = shown ? st::historyReplyHeight : 0; + if (const auto delta = height - _rootViewHeight) { + _rootViewHeight = height; + if (_scroll->scrollTop() == _scroll->scrollTopMax()) { + setGeometryWithTopMoved(geometry(), delta); } else { - _rootView->hide(); + updateControlsGeometry(); } - _rootVisible = shown; - _rootView->finishAnimating(); - _rootViewInited = true; - } else { - _rootVisible = shown; } + if (shown) { + _rootView->show(); + } else { + _rootView->hide(); + } + _rootVisible = shown; + _rootView->finishAnimating(); + _rootViewInited = true; + } else { + _rootVisible = shown; } } diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index c5ec17f7a..31ce7156d 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -842,7 +842,7 @@ bool ScheduledWidget::showAtPositionNow(Data::MessagePosition position) { } void ScheduledWidget::updateScrollDownVisibility() { - if (animating()) { + if (animatingShow()) { return; } @@ -1011,11 +1011,10 @@ void ScheduledWidget::updateControlsGeometry() { } void ScheduledWidget::paintEvent(QPaintEvent *e) { - if (animating()) { + if (animatingShow()) { SectionWidget::paintEvent(e); return; - } - if (Ui::skipPaintEvent(this, e)) { + } else if (Ui::skipPaintEvent(this, e)) { return; } //if (hasPendingResizedItems()) { diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index 37c8e7bbf..deb98a178 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -264,17 +264,20 @@ void LayerWidget::doSetInnerFocus() { void LayerWidget::paintEvent(QPaintEvent *e) { Painter p(this); - auto clip = e->rect(); - auto r = st::boxRadius; + const auto clip = e->rect(); + const auto radius = st::boxRadius; auto parts = RectPart::None | 0; - if (clip.intersects({ 0, 0, width(), r })) { - parts |= RectPart::FullTop; - } if (!_tillBottom) { - if (clip.intersects({ 0, height() - r, width(), r })) { + if (clip.intersects({ 0, height() - radius, width(), radius })) { parts |= RectPart::FullBottom; } } + if (_content->animatingShow()) { + if (clip.intersects({ 0, 0, width(), radius })) { + parts |= RectPart::FullTop; + } + parts |= RectPart::Left | RectPart::Center | RectPart::Right; + } if (parts) { Ui::FillRoundRect( p, diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 0786c12b2..5e83946cd 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_info.h" #include "styles/style_profile.h" #include "styles/style_menu_icons.h" +#include "styles/style_layers.h" namespace Info { namespace { @@ -855,7 +856,9 @@ void WrapWidget::showNewContent( && newContent->hasTopBarShadow(); animationParams.oldContentCache = grabForShowAnimation( animationParams); - animationParams.withFade = (wrap() == Wrap::Layer); + const auto layer = (wrap() == Wrap::Layer); + animationParams.withFade = layer; + animationParams.topSkip = layer ? st::boxRadius : 0; } if (saveToStack) { auto item = StackItem(); diff --git a/Telegram/SourceFiles/settings/settings_intro.cpp b/Telegram/SourceFiles/settings/settings_intro.cpp index 4f2c3d9ad..1e0acca09 100644 --- a/Telegram/SourceFiles/settings/settings_intro.cpp +++ b/Telegram/SourceFiles/settings/settings_intro.cpp @@ -102,7 +102,6 @@ object_ptr CreateIntroSettings( AddDivider(result); AddSkip(result); SetupFaq(result, false); - AddSkip(result); return result; } @@ -110,7 +109,6 @@ object_ptr CreateIntroSettings( TopBar::TopBar(QWidget *parent, const style::InfoTopBar &st) : RpWidget(parent) , _st(st) { - setAttribute(Qt::WA_OpaquePaintEvent); } void TopBar::setTitle(rpl::producer &&title) { @@ -156,8 +154,10 @@ void TopBar::updateControlsGeometry(int newWidth) { } void TopBar::paintEvent(QPaintEvent *e) { - Painter p(this); - p.fillRect(e->rect(), _st.bg); + const auto radius = st::boxRadius; + QPainter(this).fillRect( + e->rect().intersected({ 0, radius, width(), height() - radius }), + _st.bg); } } // namespace @@ -452,11 +452,7 @@ int LayerWidget::resizeGetHeight(int newWidth) { auto windowHeight = parentSize.height(); auto newLeft = (windowWidth - newWidth) / 2; if (!newLeft) { - _content->updateGeometry({ - 0, - st::boxRadius, - windowWidth, - windowHeight - st::boxRadius }, 0); + _content->updateGeometry({ 0, 0, windowWidth, windowHeight }, 0); auto newGeometry = QRect(0, 0, windowWidth, windowHeight); if (newGeometry != geometry()) { _content->forceContentRepaint(); @@ -472,12 +468,12 @@ int LayerWidget::resizeGetHeight(int newWidth) { st::infoLayerTopMinimal, st::infoLayerTopMaximal); auto newBottom = newTop; - auto desiredHeight = st::boxRadius + _desiredHeight + st::boxRadius; + auto desiredHeight = _desiredHeight + st::boxRadius; accumulate_min(desiredHeight, windowHeight - newTop - newBottom); // First resize content to new width and get the new desired height. auto contentLeft = 0; - auto contentTop = st::boxRadius; + auto contentTop = 0; auto contentBottom = st::boxRadius; auto contentWidth = newWidth; auto contentHeight = desiredHeight - contentTop - contentBottom; diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 912f95b21..7622eb911 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -153,6 +153,7 @@ void SectionWidget::showAnimated( myContentCache); _showAnimation->setTopBarShadow(params.withTopBarShadow); _showAnimation->setWithFade(params.withFade); + _showAnimation->setTopSkip(params.topSkip); _showAnimation->start(); show(); @@ -271,10 +272,14 @@ void SectionWidget::PaintBackground( void SectionWidget::paintEvent(QPaintEvent *e) { if (_showAnimation) { Painter p(this); - _showAnimation->paintContents(p, e->rect()); + _showAnimation->paintContents(p); } } +bool SectionWidget::animatingShow() const { + return (_showAnimation != nullptr); +} + void SectionWidget::showFinished() { _showAnimation.reset(); if (isHidden()) return; diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index 2ddb96016..364f9df11 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -72,6 +72,7 @@ class SectionMemento; struct SectionSlideParams { QPixmap oldContentCache; + int topSkip = 0; bool withTopBarShadow = false; bool withTabs = false; bool withFade = false; @@ -111,6 +112,7 @@ public: SlideDirection direction, const SectionSlideParams ¶ms); void showFast(); + [[nodiscard]] bool animatingShow() const; // This can be used to grab with or without top bar shadow. // This will be protected when animation preparation will be done inside. @@ -187,10 +189,6 @@ protected: setFocus(); } - bool animating() const { - return _showAnimation != nullptr; - } - ~SectionWidget(); private: diff --git a/Telegram/SourceFiles/window/window_slide_animation.cpp b/Telegram/SourceFiles/window/window_slide_animation.cpp index d035d0ed9..d37a356df 100644 --- a/Telegram/SourceFiles/window/window_slide_animation.cpp +++ b/Telegram/SourceFiles/window/window_slide_animation.cpp @@ -12,13 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Window { -void SlideAnimation::paintContents(Painter &p, const QRect &update) const { - int retina = cIntRetinaFactor(); +void SlideAnimation::paintContents(Painter &p) const { + const auto retina = style::DevicePixelRatio(); auto progress = _animation.value((_direction == SlideDirection::FromLeft) ? 0. : 1.); if (_withFade) { - p.fillRect(update, st::boxBg); - auto slideLeft = (_direction == SlideDirection::FromLeft); auto dt = slideLeft ? (1. - progress) @@ -37,12 +35,12 @@ void SlideAnimation::paintContents(Painter &p, const QRect &update) const { auto leftWidth = (leftWidthFull + leftCoord); if (leftWidth > 0) { p.setOpacity(leftAlpha); - p.drawPixmap(0, 0, leftWidth, _cacheUnder.height() / retina, _cacheUnder, (_cacheUnder.width() - leftWidth * cIntRetinaFactor()), 0, leftWidth * cIntRetinaFactor(), _cacheUnder.height()); + p.drawPixmap(0, _topSkip, _cacheUnder, (_cacheUnder.width() - leftWidth * cIntRetinaFactor()), _topSkip * retina, leftWidth * cIntRetinaFactor(), _cacheUnder.height() - _topSkip * retina); } auto rightWidth = rightWidthFull - rightCoord; if (rightWidth > 0) { p.setOpacity(rightAlpha); - p.drawPixmap(rightCoord, 0, _cacheOver, 0, 0, rightWidth * cIntRetinaFactor(), _cacheOver.height()); + p.drawPixmap(rightCoord, _topSkip, _cacheOver, 0, _topSkip * retina, rightWidth * cIntRetinaFactor(), _cacheOver.height() - _topSkip * retina); } } else { auto coordUnder = anim::interpolate(0, -st::slideShift, progress); @@ -72,6 +70,10 @@ void SlideAnimation::setTopBarShadow(bool enabled) { _topBarShadowEnabled = enabled; } +void SlideAnimation::setTopSkip(int skip) { + _topSkip = skip; +} + void SlideAnimation::setWithFade(bool withFade) { _withFade = withFade; } diff --git a/Telegram/SourceFiles/window/window_slide_animation.h b/Telegram/SourceFiles/window/window_slide_animation.h index 54d80e9e7..1743c2b34 100644 --- a/Telegram/SourceFiles/window/window_slide_animation.h +++ b/Telegram/SourceFiles/window/window_slide_animation.h @@ -18,11 +18,12 @@ enum class SlideDirection { class SlideAnimation { public: - void paintContents(Painter &p, const QRect &update) const; + void paintContents(Painter &p) const; void setDirection(SlideDirection direction); void setPixmaps(const QPixmap &oldContentCache, const QPixmap &newContentCache); void setTopBarShadow(bool enabled); + void setTopSkip(int skip); void setWithFade(bool withFade); using RepaintCallback = Fn; @@ -41,6 +42,7 @@ private: void animationCallback(); SlideDirection _direction = SlideDirection::FromRight; + int _topSkip = 0; bool _topBarShadowEnabled = false; bool _withFade = false;