Add transparent overlay window (#4746)

This commit is contained in:
nerix
2024-10-06 12:54:24 +02:00
committed by GitHub
parent 9ba7ef324d
commit afa8067a20
40 changed files with 1464 additions and 190 deletions
+29 -20
View File
@@ -68,8 +68,7 @@ int MessageLayout::getWidth() const
// Layout
// return true if redraw is required
bool MessageLayout::layout(int width, float scale, float imageScale,
MessageElementFlags flags,
bool MessageLayout::layout(const MessageLayoutContext &ctx,
bool shouldInvalidateBuffer)
{
// BenchmarkGuard benchmark("MessageLayout::layout()");
@@ -77,9 +76,9 @@ bool MessageLayout::layout(int width, float scale, float imageScale,
bool layoutRequired = false;
// check if width changed
bool widthChanged = width != this->currentLayoutWidth_;
bool widthChanged = ctx.width != this->currentLayoutWidth_;
layoutRequired |= widthChanged;
this->currentLayoutWidth_ = width;
this->currentLayoutWidth_ = ctx.width;
// check if layout state changed
const auto layoutGeneration = getApp()->getWindows()->getGeneration();
@@ -91,18 +90,18 @@ bool MessageLayout::layout(int width, float scale, float imageScale,
}
// check if work mask changed
layoutRequired |= this->currentWordFlags_ != flags;
this->currentWordFlags_ = flags; // getSettings()->getWordTypeMask();
layoutRequired |= this->currentWordFlags_ != ctx.flags;
this->currentWordFlags_ = ctx.flags; // getSettings()->getWordTypeMask();
// check if layout was requested manually
layoutRequired |= this->flags.has(MessageLayoutFlag::RequiresLayout);
this->flags.unset(MessageLayoutFlag::RequiresLayout);
// check if dpi changed
layoutRequired |= this->scale_ != scale;
this->scale_ = scale;
layoutRequired |= this->imageScale_ != imageScale;
this->imageScale_ = imageScale;
layoutRequired |= this->scale_ != ctx.scale;
this->scale_ = ctx.scale;
layoutRequired |= this->imageScale_ != ctx.imageScale;
this->imageScale_ = ctx.imageScale;
if (!layoutRequired)
{
@@ -115,7 +114,7 @@ bool MessageLayout::layout(int width, float scale, float imageScale,
}
int oldHeight = this->container_.getHeight();
this->actuallyLayout(width, flags);
this->actuallyLayout(ctx);
if (widthChanged || this->container_.getHeight() != oldHeight)
{
this->deleteBuffer();
@@ -125,7 +124,7 @@ bool MessageLayout::layout(int width, float scale, float imageScale,
return true;
}
void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
void MessageLayout::actuallyLayout(const MessageLayoutContext &ctx)
{
#ifdef FOURTF
this->layoutCount_++;
@@ -134,7 +133,7 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
auto messageFlags = this->message_->flags;
if (this->flags.has(MessageLayoutFlag::Expanded) ||
(flags.has(MessageElementFlag::ModeratorTools) &&
(ctx.flags.has(MessageElementFlag::ModeratorTools) &&
!this->message_->flags.has(MessageFlag::Disabled)))
{
messageFlags.unset(MessageFlag::Collapsed);
@@ -143,9 +142,9 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
bool hideModerated = getSettings()->hideModerated;
bool hideModerationActions = getSettings()->hideModerationActions;
bool hideSimilar = getSettings()->hideSimilar;
bool hideReplies = !flags.has(MessageElementFlag::RepliedMessage);
bool hideReplies = !ctx.flags.has(MessageElementFlag::RepliedMessage);
this->container_.beginLayout(width, this->scale_, this->imageScale_,
this->container_.beginLayout(ctx.width, this->scale_, this->imageScale_,
messageFlags);
for (const auto &element : this->message_->elements)
@@ -177,7 +176,7 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
continue;
}
element->addToContainer(this->container_, flags);
element->addToContainer(this->container_, ctx);
}
if (this->height_ != this->container_.getHeight())
@@ -201,10 +200,15 @@ MessagePaintResult MessageLayout::paint(const MessagePaintContext &ctx)
{
MessagePaintResult result;
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth,
ctx.messageColors.hasTransparency);
if (!this->bufferValid_)
{
if (ctx.messageColors.hasTransparency)
{
pixmap->fill(Qt::transparent);
}
this->updateBuffer(pixmap, ctx);
}
@@ -278,7 +282,7 @@ MessagePaintResult MessageLayout::paint(const MessagePaintContext &ctx)
return result;
}
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width, bool clear)
{
if (this->buffer_ != nullptr)
{
@@ -292,6 +296,11 @@ QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
painter.device()->devicePixelRatioF()));
this->buffer_->setDevicePixelRatio(painter.device()->devicePixelRatioF());
if (clear)
{
this->buffer_->fill(Qt::transparent);
}
this->bufferValid_ = false;
DebugCount::increase("message drawing buffers");
return this->buffer_.get();
@@ -313,10 +322,10 @@ void MessageLayout::updateBuffer(QPixmap *buffer,
if (ctx.preferences.alternateMessages &&
this->flags.has(MessageLayoutFlag::AlternateBackground))
{
return ctx.messageColors.alternate;
return ctx.messageColors.alternateBg;
}
return ctx.messageColors.regular;
return ctx.messageColors.regularBg;
}();
if (this->message_->flags.has(MessageFlag::ElevatedMessage) &&
+4 -4
View File
@@ -18,6 +18,7 @@ struct Selection;
struct MessageLayoutContainer;
class MessageLayoutElement;
struct MessagePaintContext;
struct MessageLayoutContext;
enum class MessageElementFlag : int64_t;
using MessageElementFlags = FlagsEnum<MessageElementFlag>;
@@ -56,8 +57,7 @@ public:
MessageLayoutFlags flags;
bool layout(int width, float scale_, float imageScale,
MessageElementFlags flags, bool shouldInvalidateBuffer);
bool layout(const MessageLayoutContext &ctx, bool shouldInvalidateBuffer);
// Painting
MessagePaintResult paint(const MessagePaintContext &ctx);
@@ -112,11 +112,11 @@ public:
private:
// methods
void actuallyLayout(int width, MessageElementFlags flags);
void actuallyLayout(const MessageLayoutContext &ctx);
void updateBuffer(QPixmap *buffer, const MessagePaintContext &ctx);
// Create new buffer if required, returning the buffer
QPixmap *ensureBuffer(QPainter &painter, int width);
QPixmap *ensureBuffer(QPainter &painter, int width, bool clear);
// variables
const MessagePtr message_;
+29 -6
View File
@@ -3,21 +3,44 @@
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
#include <algorithm>
namespace chatterino {
void MessageColors::applyTheme(Theme *theme)
void MessageColors::applyTheme(Theme *theme, bool isOverlay,
int backgroundOpacity)
{
this->regular = theme->messages.backgrounds.regular;
this->alternate = theme->messages.backgrounds.alternate;
auto applyColors = [this](const auto &src) {
this->regularBg = src.backgrounds.regular;
this->alternateBg = src.backgrounds.alternate;
this->disabled = theme->messages.disabled;
this->selection = theme->messages.selection;
this->system = theme->messages.textColors.system;
this->disabled = src.disabled;
this->selection = src.selection;
this->regularText = src.textColors.regular;
this->linkText = src.textColors.link;
this->systemText = src.textColors.system;
};
if (isOverlay)
{
this->channelBackground = theme->overlayMessages.background;
this->channelBackground.setAlpha(std::clamp(backgroundOpacity, 0, 255));
applyColors(theme->overlayMessages);
}
else
{
this->channelBackground = theme->splits.background;
applyColors(theme->messages);
}
this->messageSeperator = theme->splits.messageSeperator;
this->focusedLastMessageLine = theme->tabs.selected.backgrounds.regular;
this->unfocusedLastMessageLine = theme->tabs.selected.backgrounds.unfocused;
this->hasTransparency =
this->regularBg.alpha() != 255 || this->alternateBg.alpha() != 255;
}
void MessagePreferences::connectSettings(Settings *settings,
+24 -4
View File
@@ -1,5 +1,7 @@
#pragma once
#include "messages/MessageElement.hpp"
#include <QColor>
#include <QPainter>
@@ -16,18 +18,27 @@ struct Selection;
// TODO: Figure out if this could be a subset of Theme instead (e.g. Theme::MessageColors)
struct MessageColors {
QColor regular;
QColor alternate;
QColor channelBackground;
// true if any of the background colors have transparency
bool hasTransparency = false;
QColor regularBg;
QColor alternateBg;
QColor disabled;
QColor selection;
QColor system;
QColor regularText;
QColor linkText;
QColor systemText;
QColor messageSeperator;
QColor focusedLastMessageLine;
QColor unfocusedLastMessageLine;
void applyTheme(Theme *theme);
void applyTheme(Theme *theme, bool isOverlay, int backgroundOpacity);
};
// TODO: Explore if we can let settings own this
@@ -72,4 +83,13 @@ struct MessagePaintContext {
bool isLastReadMessage{};
};
struct MessageLayoutContext {
const MessageColors &messageColors;
MessageElementFlags flags;
int width = 1;
float scale = 1;
float imageScale = 1;
};
} // namespace chatterino
@@ -555,7 +555,7 @@ void TextIconLayoutElement::paint(QPainter &painter,
QFont font = app->getFonts()->getFont(FontStyle::Tiny, this->scale);
painter.setPen(messageColors.system);
painter.setPen(messageColors.systemText);
painter.setFont(font);
QTextOption option;