mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Move background caching to Window::SessionController.
This commit is contained in:
parent
1bc5277d51
commit
2667bb3568
5 changed files with 168 additions and 161 deletions
|
@ -7,14 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "mainwidget.h"
|
||||
|
||||
#include <rpl/combine.h>
|
||||
#include <rpl/merge.h>
|
||||
#include <rpl/flatten_latest.h>
|
||||
#include "api/api_updates.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_document_resolver.h"
|
||||
#include "data/data_wall_paper.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "data/data_game.h"
|
||||
#include "data/data_peer_values.h"
|
||||
|
@ -122,9 +120,6 @@ namespace {
|
|||
// Send channel views each second.
|
||||
constexpr auto kSendViewsTimeout = crl::time(1000);
|
||||
|
||||
// Cache background scaled image after 3s.
|
||||
constexpr auto kCacheBackgroundTimeout = 3000;
|
||||
|
||||
} // namespace
|
||||
|
||||
enum StackItemType {
|
||||
|
@ -239,7 +234,6 @@ MainWidget::MainWidget(
|
|||
, _dialogs(this, _controller)
|
||||
, _history(this, _controller)
|
||||
, _playerPlaylist(this, _controller)
|
||||
, _cacheBackgroundTimer([=] { cacheBackground(); })
|
||||
, _viewsIncrementTimer([=] { viewsIncrement(); })
|
||||
, _changelogs(Core::Changelogs::Create(&controller->session())) {
|
||||
setupConnectingWidget();
|
||||
|
@ -345,15 +339,6 @@ MainWidget::MainWidget(
|
|||
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
|
||||
using Update = Window::Theme::BackgroundUpdate;
|
||||
Window::Theme::Background()->updates(
|
||||
) | rpl::start_with_next([=](const Update &update) {
|
||||
if (update.type == Update::Type::New
|
||||
|| update.type == Update::Type::Changed) {
|
||||
clearCachedBackground();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
subscribe(Media::Player::instance()->playerWidgetOver(), [this](bool over) {
|
||||
if (over) {
|
||||
if (_playerPlaylist->isHidden()) {
|
||||
|
@ -780,76 +765,6 @@ bool MainWidget::selectingPeer() const {
|
|||
return _hider ? true : false;
|
||||
}
|
||||
|
||||
void MainWidget::cacheBackground() {
|
||||
const auto background = Window::Theme::Background();
|
||||
if (background->colorForFill()) {
|
||||
return;
|
||||
}
|
||||
const auto gradient = background->gradientForFill();
|
||||
const auto patternOpacity = background->paper().patternOpacity();
|
||||
const auto &bg = background->pixmap();
|
||||
if (background->tile() || bg.isNull()) {
|
||||
auto result = gradient.isNull()
|
||||
? QImage(
|
||||
_willCacheFor.size() * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied)
|
||||
: gradient.scaled(
|
||||
_willCacheFor.size() * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
if (!bg.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();
|
||||
auto sx = 0;
|
||||
auto sy = 0;
|
||||
auto cx = qCeil(_willCacheFor.width() / w);
|
||||
auto cy = qCeil(_willCacheFor.height() / h);
|
||||
for (int i = sx; i < cx; ++i) {
|
||||
for (int j = sy; j < cy; ++j) {
|
||||
p.drawPixmap(QPointF(i * w, j * h), tiled);
|
||||
}
|
||||
}
|
||||
}
|
||||
_cachedX = 0;
|
||||
_cachedY = 0;
|
||||
_cachedBackground = Ui::PixmapFromImage(std::move(result));
|
||||
} else {
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(_willCacheFor, bg.size(), to, from);
|
||||
auto image = bg.toImage().copy(from).scaled(
|
||||
to.width() * cIntRetinaFactor(),
|
||||
to.height() * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
auto result = gradient.isNull()
|
||||
? std::move(image)
|
||||
: gradient.scaled(
|
||||
image.size(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
if (!gradient.isNull()) {
|
||||
QPainter p(&result);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
p.drawImage(QRect(QPoint(), to.size()), image);
|
||||
}
|
||||
image = QImage();
|
||||
_cachedX = to.x();
|
||||
_cachedY = to.y();
|
||||
_cachedBackground = Ui::PixmapFromImage(std::move(result));
|
||||
_cachedBackground.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
_cachedFor = _willCacheFor;
|
||||
}
|
||||
|
||||
crl::time MainWidget::highlightStartTime(not_null<const HistoryItem*> item) const {
|
||||
return _history->highlightStartTime(item);
|
||||
}
|
||||
|
@ -1179,25 +1094,6 @@ void MainWidget::dialogsCancelled() {
|
|||
_history->activate();
|
||||
}
|
||||
|
||||
void MainWidget::clearCachedBackground() {
|
||||
_cachedBackground = QPixmap();
|
||||
_cacheBackgroundTimer.cancel();
|
||||
update();
|
||||
}
|
||||
|
||||
QPixmap MainWidget::cachedBackground(const QRect &forRect, int &x, int &y) {
|
||||
if (!_cachedBackground.isNull() && forRect == _cachedFor) {
|
||||
x = _cachedX;
|
||||
y = _cachedY;
|
||||
return _cachedBackground;
|
||||
}
|
||||
if (_willCacheFor != forRect || !_cacheBackgroundTimer.isActive()) {
|
||||
_willCacheFor = forRect;
|
||||
_cacheBackgroundTimer.callOnce(kCacheBackgroundTimeout);
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
void MainWidget::setChatBackground(
|
||||
const Data::WallPaper &background,
|
||||
QImage &&image) {
|
||||
|
|
|
@ -185,8 +185,6 @@ public:
|
|||
|
||||
void searchMessages(const QString &query, Dialogs::Key inChat);
|
||||
|
||||
QPixmap cachedBackground(const QRect &forRect, int &x, int &y);
|
||||
|
||||
void setChatBackground(
|
||||
const Data::WallPaper &background,
|
||||
QImage &&image = QImage());
|
||||
|
@ -299,9 +297,6 @@ private:
|
|||
void showAll();
|
||||
void clearHider(not_null<Window::HistoryHider*> instance);
|
||||
|
||||
void cacheBackground();
|
||||
void clearCachedBackground();
|
||||
|
||||
[[nodiscard]] auto floatPlayerDelegate()
|
||||
-> not_null<Media::Player::FloatDelegate*>;
|
||||
not_null<Ui::RpWidget*> floatPlayerWidget() override;
|
||||
|
@ -389,12 +384,6 @@ private:
|
|||
int _exportTopBarHeight = 0;
|
||||
int _contentScrollAddToY = 0;
|
||||
|
||||
QPixmap _cachedBackground;
|
||||
QRect _cachedFor, _willCacheFor;
|
||||
int _cachedX = 0;
|
||||
int _cachedY = 0;
|
||||
base::Timer _cacheBackgroundTimer;
|
||||
|
||||
PhotoData *_deletingPhoto = nullptr;
|
||||
|
||||
base::flat_map<not_null<PeerData*>, base::flat_set<MsgId>> _viewsIncremented;
|
||||
|
|
|
@ -97,51 +97,50 @@ void SectionWidget::PaintBackground(
|
|||
return;
|
||||
}
|
||||
auto fromy = controller->content()->backgroundFromY();
|
||||
auto x = 0, y = 0;
|
||||
auto cached = controller->content()->cachedBackground(fill, x, y);
|
||||
if (cached.isNull()) {
|
||||
const auto gradient = background->gradientForFill();
|
||||
const auto patternOpacity = background->paper().patternOpacity();
|
||||
const auto &bg = background->pixmap();
|
||||
if (background->tile() || bg.isNull()) {
|
||||
if (!gradient.isNull()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawImage(fill, gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
if (!bg.isNull()) {
|
||||
auto &tiled = background->pixmapForTiled();
|
||||
auto left = clip.left();
|
||||
auto top = clip.top();
|
||||
auto right = clip.left() + clip.width();
|
||||
auto bottom = clip.top() + clip.height();
|
||||
auto w = tiled.width() / cRetinaFactor();
|
||||
auto h = tiled.height() / cRetinaFactor();
|
||||
auto sx = qFloor(left / w);
|
||||
auto sy = qFloor((top - fromy) / h);
|
||||
auto cx = qCeil(right / w);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(fill, bg.size(), to, from);
|
||||
if (!gradient.isNull()) {
|
||||
p.drawImage(to, gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
to.moveTop(to.top() + fromy);
|
||||
p.drawPixmap(to, bg, from);
|
||||
auto cached = controller->cachedBackground(fill);
|
||||
if (!cached.pixmap.isNull()) {
|
||||
p.drawPixmap(cached.x, fromy + cached.y, cached.pixmap);
|
||||
return;
|
||||
}
|
||||
const auto gradient = background->gradientForFill();
|
||||
const auto patternOpacity = background->paper().patternOpacity();
|
||||
const auto &bg = background->pixmap();
|
||||
if (!bg.isNull() && !background->tile()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(fill, bg.size(), to, from);
|
||||
if (!gradient.isNull()) {
|
||||
p.drawImage(to, gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
to.moveTop(to.top() + fromy);
|
||||
p.drawPixmap(to, bg, from);
|
||||
return;
|
||||
}
|
||||
if (!gradient.isNull()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawImage(fill, gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
if (!bg.isNull()) {
|
||||
auto &tiled = background->pixmapForTiled();
|
||||
auto left = clip.left();
|
||||
auto top = clip.top();
|
||||
auto right = clip.left() + clip.width();
|
||||
auto bottom = clip.top() + clip.height();
|
||||
auto w = tiled.width() / cRetinaFactor();
|
||||
auto h = tiled.height() / cRetinaFactor();
|
||||
auto sx = qFloor(left / w);
|
||||
auto sy = qFloor((top - fromy) / h);
|
||||
auto cx = qCeil(right / w);
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.drawPixmap(x, fromy + y, cached);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "support/support_helper.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "facades.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_layers.h" // st::boxLabel
|
||||
|
@ -68,6 +69,9 @@ namespace {
|
|||
|
||||
constexpr auto kMaxChatEntryHistorySize = 50;
|
||||
|
||||
// Cache background scaled image after 3s.
|
||||
constexpr auto kCacheBackgroundTimeout = 3000;
|
||||
|
||||
} // namespace
|
||||
|
||||
void ActivateWindow(not_null<SessionController*> controller) {
|
||||
|
@ -463,7 +467,8 @@ SessionController::SessionController(
|
|||
std::make_unique<ChatHelpers::TabbedSelector>(
|
||||
_window->widget(),
|
||||
this))
|
||||
, _invitePeekTimer([=] { checkInvitePeek(); }) {
|
||||
, _invitePeekTimer([=] { checkInvitePeek(); })
|
||||
, _cacheBackgroundTimer([=] { cacheBackground(); }) {
|
||||
init();
|
||||
|
||||
if (Media::Player::instance()->pauseGifByRoundVideo()) {
|
||||
|
@ -506,6 +511,15 @@ SessionController::SessionController(
|
|||
}));
|
||||
}, _lifetime);
|
||||
|
||||
using Update = Window::Theme::BackgroundUpdate;
|
||||
Window::Theme::Background()->updates(
|
||||
) | rpl::start_with_next([=](const Update &update) {
|
||||
if (update.type == Update::Type::New
|
||||
|| update.type == Update::Type::Changed) {
|
||||
clearCachedBackground();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
session->addWindow(this);
|
||||
}
|
||||
|
||||
|
@ -1303,6 +1317,99 @@ void SessionController::openDocument(
|
|||
session().data().message(contextId));
|
||||
}
|
||||
|
||||
CachedBackground SessionController::cachedBackground(QRect area) {
|
||||
if (!_cachedBackground.pixmap.isNull()
|
||||
&& area == _cachedBackground.area) {
|
||||
return _cachedBackground;
|
||||
}
|
||||
if (_willCacheForArea != area || !_cacheBackgroundTimer.isActive()) {
|
||||
_willCacheForArea = area;
|
||||
_cacheBackgroundTimer.callOnce(kCacheBackgroundTimeout);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SessionController::cacheBackground() {
|
||||
const auto background = Window::Theme::Background();
|
||||
if (background->colorForFill()) {
|
||||
return;
|
||||
}
|
||||
const auto gradient = background->gradientForFill();
|
||||
const auto patternOpacity = background->paper().patternOpacity();
|
||||
const auto &bg = background->pixmap();
|
||||
if (background->tile() || bg.isNull()) {
|
||||
auto result = gradient.isNull()
|
||||
? QImage(
|
||||
_willCacheForArea.size() * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied)
|
||||
: gradient.scaled(
|
||||
_willCacheForArea.size() * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
if (!bg.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();
|
||||
auto sx = 0;
|
||||
auto sy = 0;
|
||||
auto cx = qCeil(_willCacheForArea.width() / w);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
_cachedBackground = CachedBackground{
|
||||
.pixmap = Ui::PixmapFromImage(std::move(result)),
|
||||
.area = _willCacheForArea,
|
||||
};
|
||||
} else {
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(
|
||||
_willCacheForArea,
|
||||
bg.size(),
|
||||
to,
|
||||
from);
|
||||
auto image = bg.toImage().copy(from).scaled(
|
||||
to.width() * cIntRetinaFactor(),
|
||||
to.height() * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
auto result = gradient.isNull()
|
||||
? std::move(image)
|
||||
: gradient.scaled(
|
||||
image.size(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
if (!gradient.isNull()) {
|
||||
QPainter p(&result);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
p.drawImage(QRect(QPoint(), to.size()), image);
|
||||
}
|
||||
image = QImage();
|
||||
_cachedBackground = {
|
||||
.pixmap = Ui::PixmapFromImage(std::move(result)),
|
||||
.area = _willCacheForArea,
|
||||
.x = to.x(),
|
||||
.y = to.y(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SessionController::clearCachedBackground() {
|
||||
_cachedBackground = {};
|
||||
_cacheBackgroundTimer.cancel();
|
||||
}
|
||||
|
||||
SessionController::~SessionController() {
|
||||
resetFakeUnreadWhileOpened();
|
||||
}
|
||||
|
|
|
@ -56,6 +56,13 @@ class SectionMemento;
|
|||
class Controller;
|
||||
class FiltersMenu;
|
||||
|
||||
struct CachedBackground {
|
||||
QPixmap pixmap;
|
||||
QRect area;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
||||
enum class GifPauseReason {
|
||||
Any = 0,
|
||||
InlineResults = (1 << 0),
|
||||
|
@ -393,6 +400,8 @@ public:
|
|||
void toggleFiltersMenu(bool enabled);
|
||||
[[nodiscard]] rpl::producer<> filtersMenuChanged() const;
|
||||
|
||||
[[nodiscard]] CachedBackground cachedBackground(QRect area);
|
||||
|
||||
rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
@ -422,6 +431,9 @@ private:
|
|||
|
||||
void checkInvitePeek();
|
||||
|
||||
void cacheBackground();
|
||||
void clearCachedBackground();
|
||||
|
||||
const not_null<Controller*> _window;
|
||||
|
||||
std::unique_ptr<Passport::FormController> _passportForm;
|
||||
|
@ -449,6 +461,10 @@ private:
|
|||
|
||||
rpl::event_stream<> _filtersMenuChanged;
|
||||
|
||||
CachedBackground _cachedBackground;
|
||||
QRect _willCacheForArea;
|
||||
base::Timer _cacheBackgroundTimer;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue