mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
perf: Only update regions with animated elements (#5043)
This commit is contained in:
parent
eb12cfa50b
commit
9612eac966
|
@ -99,7 +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)
|
- Dev: Channels without any animated elements on screen will skip updates from the GIF timer. (#5042, #5043)
|
||||||
|
|
||||||
## 2.4.6
|
## 2.4.6
|
||||||
|
|
||||||
|
|
|
@ -350,6 +350,10 @@ ChannelView::ChannelView(InternalCtor /*tag*/, QWidget *parent, Split *split,
|
||||||
auto curve = QEasingCurve();
|
auto curve = QEasingCurve();
|
||||||
curve.setCustomType(highlightEasingFunction);
|
curve.setCustomType(highlightEasingFunction);
|
||||||
this->highlightAnimation_.setEasingCurve(curve);
|
this->highlightAnimation_.setEasingCurve(curve);
|
||||||
|
QObject::connect(&this->highlightAnimation_,
|
||||||
|
&QVariantAnimation::valueChanged, this, [this] {
|
||||||
|
this->queueUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
this->messageColors_.applyTheme(getTheme());
|
this->messageColors_.applyTheme(getTheme());
|
||||||
this->messagePreferences_.connectSettings(getSettings(),
|
this->messagePreferences_.connectSettings(getSettings(),
|
||||||
|
@ -404,13 +408,13 @@ void ChannelView::initializeSignals()
|
||||||
},
|
},
|
||||||
this->signalHolder_);
|
this->signalHolder_);
|
||||||
|
|
||||||
this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested,
|
this->signalHolder_.managedConnect(
|
||||||
[&] {
|
getApp()->windows->gifRepaintRequested, [&] {
|
||||||
if (this->anyAnimationShown_)
|
if (!this->animationArea_.isEmpty())
|
||||||
{
|
{
|
||||||
this->queueUpdate();
|
this->queueUpdate(this->animationArea_);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->signalHolder_.managedConnect(
|
this->signalHolder_.managedConnect(
|
||||||
getApp()->windows->layoutRequested, [&](Channel *channel) {
|
getApp()->windows->layoutRequested, [&](Channel *channel) {
|
||||||
|
@ -580,6 +584,11 @@ void ChannelView::queueUpdate()
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelView::queueUpdate(const QRect &area)
|
||||||
|
{
|
||||||
|
this->update(area);
|
||||||
|
}
|
||||||
|
|
||||||
void ChannelView::queueLayout()
|
void ChannelView::queueLayout()
|
||||||
{
|
{
|
||||||
if (this->isVisible())
|
if (this->isVisible())
|
||||||
|
@ -1418,7 +1427,7 @@ void ChannelView::scrollToMessageLayout(MessageLayout *layout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelView::paintEvent(QPaintEvent * /*event*/)
|
void ChannelView::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
// BenchmarkGuard benchmark("paint");
|
// BenchmarkGuard benchmark("paint");
|
||||||
|
|
||||||
|
@ -1427,7 +1436,7 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/)
|
||||||
painter.fillRect(rect(), this->theme->splits.background);
|
painter.fillRect(rect(), this->theme->splits.background);
|
||||||
|
|
||||||
// draw messages
|
// draw messages
|
||||||
this->drawMessages(painter);
|
this->drawMessages(painter, event->rect());
|
||||||
|
|
||||||
// draw paused sign
|
// draw paused sign
|
||||||
if (this->paused())
|
if (this->paused())
|
||||||
|
@ -1441,7 +1450,7 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/)
|
||||||
|
|
||||||
// if overlays is false then it draws the message, if true then it draws things
|
// if overlays is false then it draws the message, if true then it draws things
|
||||||
// such as the grey overlay when a message is disabled
|
// such as the grey overlay when a message is disabled
|
||||||
void ChannelView::drawMessages(QPainter &painter)
|
void ChannelView::drawMessages(QPainter &painter, const QRect &area)
|
||||||
{
|
{
|
||||||
auto &messagesSnapshot = this->getMessagesSnapshot();
|
auto &messagesSnapshot = this->getMessagesSnapshot();
|
||||||
|
|
||||||
|
@ -1474,7 +1483,10 @@ void ChannelView::drawMessages(QPainter &painter)
|
||||||
};
|
};
|
||||||
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
|
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
|
||||||
|
|
||||||
bool anyAnimation = false;
|
QRect animationArea;
|
||||||
|
auto areaContainsY = [&area](auto y) {
|
||||||
|
return y >= area.y() && y < area.y() + area.height();
|
||||||
|
};
|
||||||
|
|
||||||
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
|
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
|
||||||
{
|
{
|
||||||
|
@ -1489,16 +1501,34 @@ void ChannelView::drawMessages(QPainter &painter)
|
||||||
ctx.isLastReadMessage = false;
|
ctx.isLastReadMessage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
anyAnimation |= layout->paint(ctx).hasAnimatedElements;
|
if (areaContainsY(ctx.y) || areaContainsY(ctx.y + layout->getHeight()))
|
||||||
|
|
||||||
if (this->highlightedMessage_ == layout)
|
|
||||||
{
|
{
|
||||||
painter.fillRect(
|
auto paintResult = layout->paint(ctx);
|
||||||
0, ctx.y, layout->getWidth(), layout->getHeight(),
|
if (paintResult.hasAnimatedElements)
|
||||||
this->highlightAnimation_.currentValue().value<QColor>());
|
|
||||||
if (this->highlightAnimation_.state() == QVariantAnimation::Stopped)
|
|
||||||
{
|
{
|
||||||
this->highlightedMessage_ = nullptr;
|
if (animationArea.isNull())
|
||||||
|
{
|
||||||
|
animationArea = QRect{0, ctx.y, layout->getWidth(),
|
||||||
|
layout->getHeight()};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
animationArea.setBottom(ctx.y + layout->getHeight());
|
||||||
|
animationArea.setWidth(
|
||||||
|
std::max(layout->getWidth(), animationArea.width()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->highlightedMessage_ == layout)
|
||||||
|
{
|
||||||
|
painter.fillRect(
|
||||||
|
0, ctx.y, layout->getWidth(), layout->getHeight(),
|
||||||
|
this->highlightAnimation_.currentValue().value<QColor>());
|
||||||
|
if (this->highlightAnimation_.state() ==
|
||||||
|
QVariantAnimation::Stopped)
|
||||||
|
{
|
||||||
|
this->highlightedMessage_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1510,7 +1540,23 @@ void ChannelView::drawMessages(QPainter &painter)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->anyAnimationShown_ = anyAnimation;
|
|
||||||
|
// Only update on a full repaint as some messages with animated elements
|
||||||
|
// might get left out in partial repaints.
|
||||||
|
// This happens for example when hovering over the go-to-bottom button.
|
||||||
|
if (this->height() <= area.height())
|
||||||
|
{
|
||||||
|
this->animationArea_ = animationArea;
|
||||||
|
}
|
||||||
|
#ifdef FOURTF
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shows the updated area on partial repaints
|
||||||
|
painter.setPen(Qt::red);
|
||||||
|
painter.drawRect(area.x(), area.y(), area.width() - 1,
|
||||||
|
area.height() - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (end == nullptr)
|
if (end == nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
size_t messagesLimit = 1000);
|
size_t messagesLimit = 1000);
|
||||||
|
|
||||||
void queueUpdate();
|
void queueUpdate();
|
||||||
|
void queueUpdate(const QRect &area);
|
||||||
Scrollbar &getScrollBar();
|
Scrollbar &getScrollBar();
|
||||||
|
|
||||||
QString getSelectedText();
|
QString getSelectedText();
|
||||||
|
@ -232,7 +233,7 @@ private:
|
||||||
void updateScrollbar(const LimitedQueueSnapshot<MessageLayoutPtr> &messages,
|
void updateScrollbar(const LimitedQueueSnapshot<MessageLayoutPtr> &messages,
|
||||||
bool causedByScrollbar, bool causedByShow);
|
bool causedByScrollbar, bool causedByShow);
|
||||||
|
|
||||||
void drawMessages(QPainter &painter);
|
void drawMessages(QPainter &painter, const QRect &area);
|
||||||
void setSelection(const SelectionItem &start, const SelectionItem &end);
|
void setSelection(const SelectionItem &start, const SelectionItem &end);
|
||||||
void setSelection(const Selection &newSelection);
|
void setSelection(const Selection &newSelection);
|
||||||
void selectWholeMessage(MessageLayout *layout, int &messageIndex);
|
void selectWholeMessage(MessageLayout *layout, int &messageIndex);
|
||||||
|
@ -273,8 +274,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().
|
/// Tracks the area of animated elements in the last full repaint.
|
||||||
bool anyAnimationShown_ = false;
|
/// If this is empty (QRect::isEmpty()), no animated element is shown.
|
||||||
|
QRect animationArea_;
|
||||||
|
|
||||||
bool pausable_ = false;
|
bool pausable_ = false;
|
||||||
QTimer pauseTimer_;
|
QTimer pauseTimer_;
|
||||||
|
|
Loading…
Reference in a new issue