perf: skip update from GIF timer if no animated elements are shown (#5042)
This commit is contained in:
@@ -99,6 +99,7 @@
|
|||||||
- Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014)
|
- Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014)
|
||||||
- Dev: Fixed most compiler warnings. (#5028)
|
- Dev: Fixed most compiler warnings. (#5028)
|
||||||
- Dev: Added the ability to show `ChannelView`s without a `Split`. (#4747)
|
- Dev: Added the ability to show `ChannelView`s without a `Split`. (#4747)
|
||||||
|
- Dev: Channels without any animated elements on screen will skip updates from the GIF timer. (#5042)
|
||||||
|
|
||||||
## 2.4.6
|
## 2.4.6
|
||||||
|
|
||||||
|
|||||||
@@ -196,8 +196,10 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Painting
|
// Painting
|
||||||
void MessageLayout::paint(const MessagePaintContext &ctx)
|
MessagePaintResult MessageLayout::paint(const MessagePaintContext &ctx)
|
||||||
{
|
{
|
||||||
|
MessagePaintResult result;
|
||||||
|
|
||||||
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
|
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
|
||||||
|
|
||||||
if (!this->bufferValid_)
|
if (!this->bufferValid_)
|
||||||
@@ -209,7 +211,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
|
|||||||
ctx.painter.drawPixmap(0, ctx.y, *pixmap);
|
ctx.painter.drawPixmap(0, ctx.y, *pixmap);
|
||||||
|
|
||||||
// draw gif emotes
|
// draw gif emotes
|
||||||
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
|
result.hasAnimatedElements =
|
||||||
|
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
|
||||||
|
|
||||||
// draw disabled
|
// draw disabled
|
||||||
if (this->message_->flags.has(MessageFlag::Disabled))
|
if (this->message_->flags.has(MessageFlag::Disabled))
|
||||||
@@ -270,6 +273,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->bufferValid_ = true;
|
this->bufferValid_ = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
|
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ enum class MessageLayoutFlag : uint8_t {
|
|||||||
};
|
};
|
||||||
using MessageLayoutFlags = FlagsEnum<MessageLayoutFlag>;
|
using MessageLayoutFlags = FlagsEnum<MessageLayoutFlag>;
|
||||||
|
|
||||||
|
struct MessagePaintResult {
|
||||||
|
bool hasAnimatedElements = false;
|
||||||
|
};
|
||||||
|
|
||||||
class MessageLayout
|
class MessageLayout
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -55,7 +59,7 @@ public:
|
|||||||
bool layout(int width, float scale_, MessageElementFlags flags);
|
bool layout(int width, float scale_, MessageElementFlags flags);
|
||||||
|
|
||||||
// Painting
|
// Painting
|
||||||
void paint(const MessagePaintContext &ctx);
|
MessagePaintResult paint(const MessagePaintContext &ctx);
|
||||||
void invalidateBuffer();
|
void invalidateBuffer();
|
||||||
void deleteBuffer();
|
void deleteBuffer();
|
||||||
void deleteCache();
|
void deleteCache();
|
||||||
|
|||||||
@@ -235,13 +235,15 @@ void MessageLayoutContainer::paintElements(QPainter &painter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
|
bool MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
|
||||||
int yOffset) const
|
int yOffset) const
|
||||||
{
|
{
|
||||||
|
bool anyAnimatedElement = false;
|
||||||
for (const auto &element : this->elements_)
|
for (const auto &element : this->elements_)
|
||||||
{
|
{
|
||||||
element->paintAnimated(painter, yOffset);
|
anyAnimatedElement |= element->paintAnimated(painter, yOffset);
|
||||||
}
|
}
|
||||||
|
return anyAnimatedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLayoutContainer::paintSelection(QPainter &painter,
|
void MessageLayoutContainer::paintSelection(QPainter &painter,
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ struct MessageLayoutContainer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Paint the animated elements in this message
|
* Paint the animated elements in this message
|
||||||
|
* @returns true if this container contains at least one animated element
|
||||||
*/
|
*/
|
||||||
void paintAnimatedElements(QPainter &painter, int yOffset) const;
|
bool paintAnimatedElements(QPainter &painter, int yOffset) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paint the selection for this container
|
* Paint the selection for this container
|
||||||
|
|||||||
@@ -153,11 +153,11 @@ void ImageLayoutElement::paint(QPainter &painter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
bool ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
||||||
{
|
{
|
||||||
if (this->image_ == nullptr)
|
if (this->image_ == nullptr)
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->image_->animated())
|
if (this->image_->animated())
|
||||||
@@ -167,8 +167,10 @@ void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
|||||||
auto rect = this->getRect();
|
auto rect = this->getRect();
|
||||||
rect.moveTop(rect.y() + yOffset);
|
rect.moveTop(rect.y() + yOffset);
|
||||||
painter.drawPixmap(QRectF(rect), *pixmap, QRectF());
|
painter.drawPixmap(QRectF(rect), *pixmap, QRectF());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
int ImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||||
@@ -265,7 +267,7 @@ void LayeredImageLayoutElement::paint(QPainter &painter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
bool LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
||||||
{
|
{
|
||||||
auto fullRect = QRectF(this->getRect());
|
auto fullRect = QRectF(this->getRect());
|
||||||
fullRect.moveTop(fullRect.y() + yOffset);
|
fullRect.moveTop(fullRect.y() + yOffset);
|
||||||
@@ -297,6 +299,7 @@ void LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return animatedFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LayeredImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
int LayeredImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||||
@@ -446,8 +449,9 @@ void TextLayoutElement::paint(QPainter &painter,
|
|||||||
QTextOption(Qt::AlignLeft | Qt::AlignTop));
|
QTextOption(Qt::AlignLeft | Qt::AlignTop));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextLayoutElement::paintAnimated(QPainter &, int)
|
bool TextLayoutElement::paintAnimated(QPainter & /*painter*/, int /*yOffset*/)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||||
@@ -567,8 +571,10 @@ void TextIconLayoutElement::paint(QPainter &painter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextIconLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
bool TextIconLayoutElement::paintAnimated(QPainter & /*painter*/,
|
||||||
|
int /*yOffset*/)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextIconLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
int TextIconLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||||
@@ -640,8 +646,10 @@ void ReplyCurveLayoutElement::paint(QPainter &painter,
|
|||||||
painter.drawPath(path);
|
painter.drawPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyCurveLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
bool ReplyCurveLayoutElement::paintAnimated(QPainter & /*painter*/,
|
||||||
|
int /*yOffset*/)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReplyCurveLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
int ReplyCurveLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ public:
|
|||||||
virtual size_t getSelectionIndexCount() const = 0;
|
virtual size_t getSelectionIndexCount() const = 0;
|
||||||
virtual void paint(QPainter &painter,
|
virtual void paint(QPainter &painter,
|
||||||
const MessageColors &messageColors) = 0;
|
const MessageColors &messageColors) = 0;
|
||||||
virtual void paintAnimated(QPainter &painter, int yOffset) = 0;
|
/// @returns true if anything was painted
|
||||||
|
virtual bool paintAnimated(QPainter &painter, int yOffset) = 0;
|
||||||
virtual int getMouseOverIndex(const QPoint &abs) const = 0;
|
virtual int getMouseOverIndex(const QPoint &abs) const = 0;
|
||||||
virtual int getXFromIndex(size_t index) = 0;
|
virtual int getXFromIndex(size_t index) = 0;
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ protected:
|
|||||||
uint32_t to = UINT32_MAX) const override;
|
uint32_t to = UINT32_MAX) const override;
|
||||||
size_t getSelectionIndexCount() const override;
|
size_t getSelectionIndexCount() const override;
|
||||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
bool paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(size_t index) override;
|
int getXFromIndex(size_t index) override;
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ protected:
|
|||||||
uint32_t to = UINT32_MAX) const override;
|
uint32_t to = UINT32_MAX) const override;
|
||||||
size_t getSelectionIndexCount() const override;
|
size_t getSelectionIndexCount() const override;
|
||||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
bool paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(size_t index) override;
|
int getXFromIndex(size_t index) override;
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ protected:
|
|||||||
uint32_t to = UINT32_MAX) const override;
|
uint32_t to = UINT32_MAX) const override;
|
||||||
size_t getSelectionIndexCount() const override;
|
size_t getSelectionIndexCount() const override;
|
||||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
bool paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(size_t index) override;
|
int getXFromIndex(size_t index) override;
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ protected:
|
|||||||
uint32_t to = UINT32_MAX) const override;
|
uint32_t to = UINT32_MAX) const override;
|
||||||
size_t getSelectionIndexCount() const override;
|
size_t getSelectionIndexCount() const override;
|
||||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
bool paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(size_t index) override;
|
int getXFromIndex(size_t index) override;
|
||||||
|
|
||||||
@@ -200,7 +201,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
bool paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(size_t index) override;
|
int getXFromIndex(size_t index) override;
|
||||||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||||
|
|||||||
@@ -406,7 +406,10 @@ void ChannelView::initializeSignals()
|
|||||||
|
|
||||||
this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested,
|
this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested,
|
||||||
[&] {
|
[&] {
|
||||||
this->queueUpdate();
|
if (this->anyAnimationShown_)
|
||||||
|
{
|
||||||
|
this->queueUpdate();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->signalHolder_.managedConnect(
|
this->signalHolder_.managedConnect(
|
||||||
@@ -1470,6 +1473,8 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||||||
};
|
};
|
||||||
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
|
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
|
||||||
|
|
||||||
|
bool anyAnimation = false;
|
||||||
|
|
||||||
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
|
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
|
||||||
{
|
{
|
||||||
MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get();
|
MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get();
|
||||||
@@ -1483,7 +1488,7 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||||||
ctx.isLastReadMessage = false;
|
ctx.isLastReadMessage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
layout->paint(ctx);
|
anyAnimation |= layout->paint(ctx).hasAnimatedElements;
|
||||||
|
|
||||||
if (this->highlightedMessage_ == layout)
|
if (this->highlightedMessage_ == layout)
|
||||||
{
|
{
|
||||||
@@ -1504,6 +1509,7 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this->anyAnimationShown_ = anyAnimation;
|
||||||
|
|
||||||
if (end == nullptr)
|
if (end == nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -273,6 +273,9 @@ private:
|
|||||||
bool lastMessageHasAlternateBackground_ = false;
|
bool lastMessageHasAlternateBackground_ = false;
|
||||||
bool lastMessageHasAlternateBackgroundReverse_ = true;
|
bool lastMessageHasAlternateBackgroundReverse_ = true;
|
||||||
|
|
||||||
|
/// Tracks if this view has painted any animated element in the last #paintEvent().
|
||||||
|
bool anyAnimationShown_ = false;
|
||||||
|
|
||||||
bool pausable_ = false;
|
bool pausable_ = false;
|
||||||
QTimer pauseTimer_;
|
QTimer pauseTimer_;
|
||||||
std::unordered_map<PauseReason, std::optional<SteadyClock::time_point>>
|
std::unordered_map<PauseReason, std::optional<SteadyClock::time_point>>
|
||||||
|
|||||||
Reference in New Issue
Block a user