Animated transition on pattern-on-gradient resize.

This commit is contained in:
John Preston 2021-08-13 21:18:06 +03:00
parent b9a9520ef5
commit 3dadcd9352
17 changed files with 213 additions and 135 deletions

View file

@ -26,7 +26,7 @@ object_ptr<Window::SectionWidget> TabbedMemento::createWidget(
TabbedSection::TabbedSection(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Window::SectionWidget(parent, controller)
: Window::SectionWidget(parent, controller, PaintedBackground::Custom)
, _selector(controller->tabbedSelector()) {
_selector->setParent(this);
_selector->setRoundRadius(0);

View file

@ -164,7 +164,7 @@ void Widget::BottomButton::paintEvent(QPaintEvent *e) {
Widget::Widget(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Window::AbstractSectionWidget(parent, controller)
: Window::AbstractSectionWidget(parent, controller, PaintedBackground::Custom)
, _api(&controller->session().mtp())
, _searchControls(this)
, _mainMenuToggle(_searchControls, st::dialogsMenuToggle)

View file

@ -275,11 +275,14 @@ Widget::Widget(
QWidget *parent,
not_null<Window::SessionController*> controller,
not_null<ChannelData*> channel)
: Window::SectionWidget(parent, controller)
: Window::SectionWidget(parent, controller, PaintedBackground::Section)
, _scroll(this, st::historyScroll, false)
, _fixedBar(this, controller, channel)
, _fixedBarShadow(this)
, _whatIsThis(this, tr::lng_admin_log_about(tr::now).toUpper(), st::historyComposeButton) {
, _whatIsThis(
this,
tr::lng_admin_log_about(tr::now).toUpper(),
st::historyComposeButton) {
_fixedBar->move(0, 0);
_fixedBar->resizeToWidth(width());
_fixedBar->showFilterRequests(
@ -303,6 +306,11 @@ Widget::Widget(
updateAdaptiveLayout();
}, lifetime());
controller->repaintBackgroundRequests(
) | rpl::start_with_next([=] {
update();
}, lifetime());
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, controller, channel));
_inner->showSearchSignal(
) | rpl::start_with_next([=] {

View file

@ -171,7 +171,7 @@ const auto kPsaAboutPrefix = "cloud_lng_about_psa_";
HistoryWidget::HistoryWidget(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Window::AbstractSectionWidget(parent, controller)
: Window::AbstractSectionWidget(parent, controller, PaintedBackground::Section)
, _api(&controller->session().mtp())
, _updateEditTimeLeftDisplay([=] { updateField(); })
, _fieldBarCancel(this, st::historyReplyCancel)
@ -432,6 +432,11 @@ HistoryWidget::HistoryWidget(
}
}, lifetime());
controller->repaintBackgroundRequests(
) | rpl::start_with_next([=] {
update();
}, lifetime());
session().data().newItemAdded(
) | rpl::start_with_next([=](not_null<HistoryItem*> item) {
newItemAdded(item);

View file

@ -90,7 +90,7 @@ PinnedWidget::PinnedWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
not_null<History*> history)
: Window::SectionWidget(parent, controller)
: Window::SectionWidget(parent, controller, PaintedBackground::Section)
, _history(history->migrateToOrMe())
, _migratedPeer(_history->peer->migrateFrom())
, _topBar(this, controller)

View file

@ -146,7 +146,7 @@ RepliesWidget::RepliesWidget(
not_null<Window::SessionController*> controller,
not_null<History*> history,
MsgId rootId)
: Window::SectionWidget(parent, controller)
: Window::SectionWidget(parent, controller, PaintedBackground::Section)
, _history(history)
, _rootId(rootId)
, _root(lookupRoot())

View file

@ -90,7 +90,7 @@ ScheduledWidget::ScheduledWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
not_null<History*> history)
: Window::SectionWidget(parent, controller)
: Window::SectionWidget(parent, controller, PaintedBackground::Section)
, _history(history)
, _scroll(this, st::historyScroll, false)
, _topBar(this, controller)

View file

@ -24,7 +24,7 @@ SectionWidget::SectionWidget(
not_null<Window::SessionController*> window,
Wrap wrap,
not_null<Memento*> memento)
: Window::SectionWidget(parent, window)
: Window::SectionWidget(parent, window, PaintedBackground::Custom)
, _content(this, window, wrap, memento) {
init();
}
@ -34,7 +34,7 @@ SectionWidget::SectionWidget(
not_null<Window::SessionController*> window,
Wrap wrap,
not_null<MoveMemento*> memento)
: Window::SectionWidget(parent, window)
: Window::SectionWidget(parent, window, PaintedBackground::Custom)
, _content(memento->takeContent(this, wrap)) {
init();
}

View file

@ -59,7 +59,7 @@ WrapWidget::WrapWidget(
not_null<Window::SessionController*> window,
Wrap wrap,
not_null<Memento*> memento)
: SectionWidget(parent, window)
: SectionWidget(parent, window, PaintedBackground::Custom)
, _wrap(wrap)
, _controller(createController(window, memento->content()))
, _topShadow(this) {

View file

@ -571,18 +571,21 @@ void BackgroundRow::updateImage() {
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
p.setOpacity(patternOpacity);
}
const auto &pix = background->pixmap();
if (!pix.isNull()) {
const auto sx = (pix.width() > pix.height())
? ((pix.width() - pix.height()) / 2)
const auto &prepared = background->prepared();
if (!prepared.isNull()) {
const auto sx = (prepared.width() > prepared.height())
? ((prepared.width() - prepared.height()) / 2)
: 0;
const auto sy = (pix.height() > pix.width())
? ((pix.height() - pix.width()) / 2)
const auto sy = (prepared.height() > prepared.width())
? ((prepared.height() - prepared.width()) / 2)
: 0;
const auto s = (pix.width() > pix.height())
? pix.height()
: pix.width();
p.drawPixmap(0, 0, size, size, pix, sx, sy, s, s);
const auto s = (prepared.width() > prepared.height())
? prepared.height()
: prepared.width();
p.drawImage(
QRect(0, 0, size, size),
prepared,
QRect(sx, sy, s, s));
}
}
}

View file

@ -18,14 +18,29 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Window {
AbstractSectionWidget::AbstractSectionWidget(
QWidget *parent,
not_null<SessionController*> controller,
PaintedBackground paintedBackground)
: RpWidget(parent)
, _controller(controller) {
if (paintedBackground == PaintedBackground::Section) {
controller->repaintBackgroundRequests(
) | rpl::start_with_next([=] {
update();
}, lifetime());
}
}
Main::Session &AbstractSectionWidget::session() const {
return _controller->session();
}
SectionWidget::SectionWidget(
QWidget *parent,
not_null<Window::SessionController*> controller)
: AbstractSectionWidget(parent, controller) {
not_null<Window::SessionController*> controller,
PaintedBackground paintedBackground)
: AbstractSectionWidget(parent, controller, paintedBackground) {
}
void SectionWidget::setGeometryWithTopMoved(
@ -99,18 +114,16 @@ void SectionWidget::PaintBackground(
const auto gradient = background->gradientForFill();
const auto fill = QSize(widget->width(), fullHeight);
auto fromy = controller->content()->backgroundFromY();
auto cached = controller->cachedBackground(fill);
const auto goodCache = (cached.area == fill);
const auto useCached = goodCache || !gradient.isNull();
if (!cached.pixmap.isNull()) {
auto state = controller->backgroundState(fill);
const auto paintCache = [&](const CachedBackground &cache) {
const auto to = QRect(
QPoint(cached.x, fromy + cached.y),
cached.pixmap.size() / cIntRetinaFactor());
if (goodCache) {
p.drawPixmap(to, cached.pixmap);
QPoint(cache.x, fromy + cache.y),
cache.pixmap.size() / cIntRetinaFactor());
if (cache.area == fill) {
p.drawPixmap(to, cache.pixmap);
} else {
const auto sx = fill.width() / float64(cached.area.width());
const auto sy = fill.height() / float64(cached.area.height());
const auto sx = fill.width() / float64(cache.area.width());
const auto sy = fill.height() / float64(cache.area.height());
const auto round = [](float64 value) -> int {
return (value >= 0.)
? int(std::ceil(value))
@ -122,17 +135,27 @@ void SectionWidget::PaintBackground(
sto.y(),
round((to.x() + to.width()) * sx) - sto.x(),
round((to.y() + to.height()) * sy) - sto.y(),
cached.pixmap);
cache.pixmap);
}
};
const auto goodNow = !state.now.pixmap.isNull()
&& (state.now.area == fill);
const auto useCache = goodNow || !gradient.isNull();
if (useCache) {
if (state.shown < 1. && !gradient.isNull()) {
paintCache(state.was);
p.setOpacity(state.shown);
}
paintCache(state.now);
return;
}
const auto patternOpacity = background->paper().patternOpacity();
const auto &bg = background->pixmap();
if (!bg.isNull() && !background->tile()) {
auto hq = PainterHighQualityEnabler(p);
const auto &prepared = background->prepared();
if (!prepared.isNull() && !background->tile()) {
const auto hq = PainterHighQualityEnabler(p);
const auto rects = Window::Theme::ComputeBackgroundRects(
fill,
bg.size());
prepared.size());
if (!gradient.isNull()) {
p.drawImage(rects.to, gradient);
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
@ -140,17 +163,17 @@ void SectionWidget::PaintBackground(
}
auto to = rects.to;
to.moveTop(to.top() + fromy);
p.drawPixmap(to, bg, rects.from);
p.drawImage(to, prepared, rects.from);
return;
}
if (!gradient.isNull()) {
auto hq = PainterHighQualityEnabler(p);
const auto hq = PainterHighQualityEnabler(p);
p.drawImage(QRect(QPoint(0, fromy), fill), gradient);
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
p.setOpacity(patternOpacity);
}
if (!bg.isNull()) {
auto &tiled = background->pixmapForTiled();
if (!prepared.isNull()) {
const auto &tiled = background->preparedForTiled();
auto left = clip.left();
auto top = clip.top();
auto right = clip.left() + clip.width();
@ -163,7 +186,7 @@ void SectionWidget::PaintBackground(
auto cy = qCeil((bottom - fromy) / h);
for (auto i = sx; i < cx; ++i) {
for (auto j = sy; j < cy; ++j) {
p.drawPixmap(QPointF(i * w, fromy + j * h), tiled);
p.drawImage(QPointF(i * w, fromy + j * h), tiled);
}
}
}

View file

@ -40,12 +40,14 @@ class AbstractSectionWidget
, public Media::Player::FloatSectionDelegate
, protected base::Subscriber {
public:
enum class PaintedBackground {
Section,
Custom,
};
AbstractSectionWidget(
QWidget *parent,
not_null<SessionController*> controller)
: RpWidget(parent)
, _controller(controller) {
}
not_null<SessionController*> controller,
PaintedBackground paintedBackground);
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] not_null<SessionController*> controller() const {
@ -84,7 +86,8 @@ class SectionWidget : public AbstractSectionWidget {
public:
SectionWidget(
QWidget *parent,
not_null<SessionController*> controller);
not_null<SessionController*> controller,
PaintedBackground paintedBackground);
virtual Dialogs::RowDescriptor activeChat() const {
return {};

View file

@ -730,8 +730,8 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
Assert(colorForFill()
|| !_gradient.isNull()
|| (!_original.isNull()
&& !_pixmap.isNull()
&& !_pixmapForTiled.isNull()));
&& !_prepared.isNull()
&& !_preparedForTiled.isNull()));
_updates.fire({ BackgroundUpdate::Type::New, tile() }); // delayed?
if (needResetAdjustable) {
@ -763,46 +763,42 @@ void ChatBackground::setPrepared(
}
_original = std::move(original);
_prepared = std::move(prepared);
_gradient = std::move(gradient);
preparePixmaps(std::move(prepared));
_imageMonoColor = _gradient.isNull()
? CalculateImageMonoColor(_prepared)
: std::nullopt;
prepareImageForTiled();
}
void ChatBackground::preparePixmaps(QImage image) {
const auto width = image.width();
const auto height = image.height();
void ChatBackground::prepareImageForTiled() {
const auto width = _prepared.width();
const auto height = _prepared.height();
const auto isSmallForTiled = (width > 0 && height > 0)
&& (width < kMinimumTiledSize || height < kMinimumTiledSize);
if (isSmallForTiled) {
const auto repeatTimesX = qCeil(kMinimumTiledSize / (1. * width));
const auto repeatTimesY = qCeil(kMinimumTiledSize / (1. * height));
auto imageForTiled = QImage(
width * repeatTimesX,
height * repeatTimesY,
QImage::Format_ARGB32_Premultiplied);
imageForTiled.setDevicePixelRatio(image.devicePixelRatio());
auto imageForTiledBytes = imageForTiled.bits();
auto bytesInLine = width * sizeof(uint32);
for (auto timesY = 0; timesY != repeatTimesY; ++timesY) {
auto imageBytes = image.constBits();
for (auto y = 0; y != height; ++y) {
for (auto timesX = 0; timesX != repeatTimesX; ++timesX) {
memcpy(imageForTiledBytes, imageBytes, bytesInLine);
imageForTiledBytes += bytesInLine;
}
imageBytes += image.bytesPerLine();
imageForTiledBytes += imageForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
}
}
_pixmapForTiled = Ui::PixmapFromImage(std::move(imageForTiled));
}
_imageMonoColor = _gradient.isNull()
? CalculateImageMonoColor(image)
: std::nullopt;
_pixmap = image.isNull()
? QPixmap()
: Ui::PixmapFromImage(std::move(image));
if (!isSmallForTiled) {
_pixmapForTiled = _pixmap;
_preparedForTiled = _prepared;
return;
}
const auto repeatTimesX = qCeil(kMinimumTiledSize / (1. * width));
const auto repeatTimesY = qCeil(kMinimumTiledSize / (1. * height));
_preparedForTiled = QImage(
width * repeatTimesX,
height * repeatTimesY,
QImage::Format_ARGB32_Premultiplied);
_preparedForTiled.setDevicePixelRatio(_prepared.devicePixelRatio());
auto imageForTiledBytes = _preparedForTiled.bits();
auto bytesInLine = width * sizeof(uint32);
for (auto timesY = 0; timesY != repeatTimesY; ++timesY) {
auto imageBytes = _prepared.constBits();
for (auto y = 0; y != height; ++y) {
for (auto timesX = 0; timesX != repeatTimesX; ++timesX) {
memcpy(imageForTiledBytes, imageBytes, bytesInLine);
imageForTiledBytes += bytesInLine;
}
imageBytes += _prepared.bytesPerLine();
imageForTiledBytes += _preparedForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
}
}
}
@ -868,7 +864,7 @@ void ChatBackground::adjustPaletteUsingColor(QColor color) {
}
std::optional<QColor> ChatBackground::colorForFill() const {
return !_pixmap.isNull()
return !_prepared.isNull()
? imageMonoColor()
: !_gradient.isNull()
? std::nullopt
@ -888,13 +884,12 @@ QImage ChatBackground::createCurrentImage() const {
result.fill(*fill);
return result;
} else if (_gradient.isNull()) {
return pixmap().toImage();
} else if (pixmap().isNull()) {
return _prepared;
} else if (_prepared.isNull()) {
return _gradient;
}
const auto &pattern = pixmap();
auto result = _gradient.scaled(
pattern.size(),
_prepared.size(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
result.setDevicePixelRatio(1.);
@ -902,7 +897,7 @@ QImage ChatBackground::createCurrentImage() const {
auto p = QPainter(&result);
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
p.setOpacity(paper().patternOpacity());
p.drawPixmap(QRect(QPoint(), pattern.size()), pattern);
p.drawImage(QRect(QPoint(), _prepared.size()), _prepared);
}
return result;
}
@ -1044,7 +1039,7 @@ void ChatBackground::setTestingTheme(Instance &&theme) {
saveForRevert();
set(
Data::details::TestingEditorWallPaper(),
std::move(_pixmap).toImage());
base::take(_prepared));
}
} else if (switchToThemeBackground) {
saveForRevert();

View file

@ -170,11 +170,11 @@ public:
[[nodiscard]] WallPaperId id() const {
return _paper.id();
}
[[nodiscard]] const QPixmap &pixmap() const {
return _pixmap;
[[nodiscard]] const QImage &prepared() const {
return _prepared;
}
[[nodiscard]] const QPixmap &pixmapForTiled() const {
return _pixmapForTiled;
[[nodiscard]] const QImage &preparedForTiled() const {
return _preparedForTiled;
}
[[nodiscard]] std::optional<QColor> colorForFill() const;
[[nodiscard]] QImage gradientForFill() const;
@ -197,7 +197,7 @@ private:
void initialRead();
void saveForRevert();
void setPrepared(QImage original, QImage prepared, QImage gradient);
void preparePixmaps(QImage image);
void prepareImageForTiled();
void writeNewBackgroundSettings();
void setPaper(const Data::WallPaper &paper);
@ -239,8 +239,8 @@ private:
std::optional<QColor> _paperColor;
QImage _gradient;
QImage _original;
QPixmap _pixmap;
QPixmap _pixmapForTiled;
QImage _prepared;
QImage _preparedForTiled;
bool _nightMode = false;
bool _tileDayValue = false;
bool _tileNightValue = true;

View file

@ -988,10 +988,11 @@ void MainMenu::refreshBackground() {
const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c);
const auto background = Window::Theme::Background();
const auto &paper = background->paper();
const auto &pixmap = background->pixmap();
const auto &prepared = background->prepared();
QRect to, from;
const auto rects = Window::Theme::ComputeBackgroundRects(fill, pixmap.size());
const auto rects = Window::Theme::ComputeBackgroundRects(
fill,
prepared.size());
auto backgroundImage = !paper.backgroundColors().empty()
? Data::GenerateWallPaper(
@ -999,7 +1000,7 @@ void MainMenu::refreshBackground() {
paper.backgroundColors(),
paper.gradientRotation(),
paper.patternOpacity(),
[&](QPainter &p) { p.drawPixmap(to, pixmap, from); })
[&](QPainter &p) { p.drawImage(rects.to, prepared, rects.from); })
: QImage(
fill * cIntRetinaFactor(),
QImage::Format_ARGB32_Premultiplied);
@ -1029,7 +1030,7 @@ void MainMenu::refreshBackground() {
// Background image.
if (!paper.isPattern()) {
p.drawPixmap(to, pixmap, from);
p.drawImage(rects.to, prepared, rects.from);
}
// Cut off the part of the background that is under text.

View file

@ -72,6 +72,7 @@ namespace {
constexpr auto kMaxChatEntryHistorySize = 50;
constexpr auto kCacheBackgroundTimeout = 3 * crl::time(1000);
constexpr auto kCacheBackgroundFastTimeout = crl::time(200);
constexpr auto kBackgroundFadeDuration = crl::time(200);
} // namespace
@ -1318,15 +1319,16 @@ void SessionController::openDocument(
session().data().message(contextId));
}
CachedBackground SessionController::cachedBackground(QSize area) {
if (_cachedBackground.area != area) {
const BackgroundState &SessionController::backgroundState(QSize area) {
_backgroundState.shown = _backgroundFade.value(1.);
if (_backgroundState.now.area != area) {
if (_willCacheForArea != area || !_cacheBackgroundTimer.isActive()) {
_willCacheForArea = area;
_lastAreaChangeTime = crl::now();
_cacheBackgroundTimer.callOnce(kCacheBackgroundFastTimeout);
}
}
return _cachedBackground;
return _backgroundState;
}
void SessionController::cacheBackground() {
@ -1342,8 +1344,8 @@ void SessionController::cacheBackground() {
}
const auto gradient = background->gradientForFill();
const auto patternOpacity = background->paper().patternOpacity();
const auto &bg = background->pixmap();
if (background->tile() || bg.isNull()) {
const auto &prepared = background->prepared();
if (background->tile() || prepared.isNull()) {
auto result = gradient.isNull()
? QImage(
_willCacheForArea * cIntRetinaFactor(),
@ -1353,34 +1355,34 @@ void SessionController::cacheBackground() {
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
result.setDevicePixelRatio(cRetinaFactor());
if (!bg.isNull()) {
if (!prepared.isNull()) {
QPainter p(&result);
if (!gradient.isNull()) {
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
p.setOpacity(patternOpacity);
}
const auto &tiled = background->pixmapForTiled();
auto w = tiled.width() / cRetinaFactor();
auto h = tiled.height() / cRetinaFactor();
const auto &tiled = background->preparedForTiled();
const auto w = tiled.width() / cRetinaFactor();
const auto h = tiled.height() / cRetinaFactor();
auto sx = 0;
auto sy = 0;
auto cx = qCeil(_willCacheForArea.width() / w);
auto cy = qCeil(_willCacheForArea.height() / h);
const auto cx = qCeil(_willCacheForArea.width() / w);
const auto cy = qCeil(_willCacheForArea.height() / h);
for (int i = sx; i < cx; ++i) {
for (int j = sy; j < cy; ++j) {
p.drawPixmap(QPointF(i * w, j * h), tiled);
p.drawImage(QPointF(i * w, j * h), tiled);
}
}
}
_cachedBackground = CachedBackground{
setCachedBackground({
.pixmap = Ui::PixmapFromImage(std::move(result)),
.area = _willCacheForArea,
};
});
} else {
const auto rects = Window::Theme::ComputeBackgroundRects(
_willCacheForArea,
bg.size());
auto image = bg.toImage().copy(rects.from).scaled(
prepared.size());
auto image = prepared.copy(rects.from).scaled(
rects.to.width() * cIntRetinaFactor(),
rects.to.height() * cIntRetinaFactor(),
Qt::IgnoreAspectRatio,
@ -1399,21 +1401,51 @@ void SessionController::cacheBackground() {
p.drawImage(QRect(QPoint(), rects.to.size()), image);
}
image = QImage();
_cachedBackground = {
setCachedBackground({
.pixmap = Ui::PixmapFromImage(std::move(result)),
.area = _willCacheForArea,
.x = rects.to.x(),
.y = rects.to.y(),
};
}
if (!gradient.isNull()) {
content()->update();
});
}
}
void SessionController::setCachedBackground(CachedBackground &&cached) {
const auto background = Window::Theme::Background();
if (background->gradientForFill().isNull()
|| _backgroundState.now.pixmap.isNull()) {
_backgroundFade.stop();
_backgroundState.shown = 1.;
_backgroundState.now = std::move(cached);
return;
}
// #TODO themes compose several transitions.
_backgroundState.was = std::move(_backgroundState.now);
_backgroundState.now = std::move(cached);
_backgroundState.shown = 0.;
const auto callback = [=] {
if (!_backgroundFade.animating()) {
_backgroundState.was = {};
_backgroundState.shown = 1.;
}
_repaintBackgroundRequests.fire({});
};
_backgroundFade.start(
callback,
0.,
1.,
kBackgroundFadeDuration);
}
void SessionController::clearCachedBackground() {
_cachedBackground = {};
_backgroundState = {};
_backgroundFade.stop();
_cacheBackgroundTimer.cancel();
_repaintBackgroundRequests.fire({});
}
rpl::producer<> SessionController::repaintBackgroundRequests() const {
return _repaintBackgroundRequests.events();
}
SessionController::~SessionController() {

View file

@ -7,13 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include <rpl/variable.h>
#include "base/flags.h"
#include "base/object_ptr.h"
#include "base/weak_ptr.h"
#include "base/timer.h"
#include "dialogs/dialogs_key.h"
#include "ui/effects/animation_value.h"
#include "ui/effects/animations.h"
#include "ui/layers/layer_widget.h"
#include "window/window_adaptive.h"
@ -63,6 +62,12 @@ struct CachedBackground {
int y = 0;
};
struct BackgroundState {
CachedBackground was;
CachedBackground now;
float64 shown = 1.;
};
enum class GifPauseReason {
Any = 0,
InlineResults = (1 << 0),
@ -232,7 +237,6 @@ private:
MsgId _showingRepliesRootId = 0;
mtpRequestId _showingRepliesRequestId = 0;
};
class SessionController : public SessionNavigation {
@ -296,11 +300,11 @@ public:
void floatPlayerAreaUpdated();
struct ColumnLayout {
int bodyWidth;
int dialogsWidth;
int chatWidth;
int thirdWidth;
Adaptive::WindowLayout windowLayout;
int bodyWidth = 0;
int dialogsWidth = 0;
int chatWidth = 0;
int thirdWidth = 0;
Adaptive::WindowLayout windowLayout = Adaptive::WindowLayout();
};
[[nodiscard]] ColumnLayout computeColumnLayout() const;
int dialogsSmallColumnWidth() const;
@ -400,7 +404,8 @@ public:
void toggleFiltersMenu(bool enabled);
[[nodiscard]] rpl::producer<> filtersMenuChanged() const;
[[nodiscard]] CachedBackground cachedBackground(QSize area);
[[nodiscard]] const BackgroundState &backgroundState(QSize area);
[[nodiscard]] rpl::producer<> repaintBackgroundRequests() const;
rpl::lifetime &lifetime() {
return _lifetime;
@ -433,6 +438,7 @@ private:
void cacheBackground();
void clearCachedBackground();
void setCachedBackground(CachedBackground &&cached);
const not_null<Controller*> _window;
@ -461,10 +467,12 @@ private:
rpl::event_stream<> _filtersMenuChanged;
CachedBackground _cachedBackground;
BackgroundState _backgroundState;
Ui::Animations::Simple _backgroundFade;
QSize _willCacheForArea;
crl::time _lastAreaChangeTime = 0;
base::Timer _cacheBackgroundTimer;
rpl::event_stream<> _repaintBackgroundRequests;
rpl::lifetime _lifetime;