diff --git a/CHANGELOG.md b/CHANGELOG.md index ace836f8e2a..8f17f4bcc4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Bugfix: Fixed the Quick Switcher (CTRL+K) from sometimes showing up on the wrong window. (#4819) - Bugfix: Fixed too much text being copied when copying chat messages. (#4812, #4830, #4839) - Bugfix: Fixed empty page being added when showing out of bounds dialog. (#4849) +- Bugfix: Fixed broken scaling in context menus. (#4868) - Dev: Fixed UTF16 encoding of `modes` file for the installer. (#4791) - Dev: Temporarily disable High DPI scaling on Qt6 builds on Windows. (#4767) - Dev: Tests now run on Ubuntu 22.04 instead of 20.04 to loosen C++ restrictions in tests. (#4774) diff --git a/resources/qss/settings.qss b/resources/qss/settings.qss index 6d5114423b0..93c69b603ed 100644 --- a/resources/qss/settings.qss +++ b/resources/qss/settings.qss @@ -1,11 +1,11 @@ * { - font-size: px; + font-size: 14px; font-family: "Segoe UI"; } QCheckBox::indicator { - width: px; - height: px; + width: 14px; + height: 14px; } chatterino--ComboBox { diff --git a/src/RunGui.cpp b/src/RunGui.cpp index ce36d7a9114..c841ecfcd60 100644 --- a/src/RunGui.cpp +++ b/src/RunGui.cpp @@ -75,11 +75,7 @@ namespace { void initQt() { // set up the QApplication flags - QApplication::setAttribute(Qt::AA_Use96Dpi, true); -#ifdef Q_OS_WIN32 - QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true); -#endif - + QApplication::setAttribute(Qt::AA_Use96Dpi); QApplication::setStyle(QStyleFactory::create("Fusion")); #ifndef Q_OS_MAC diff --git a/src/main.cpp b/src/main.cpp index 9dce310a0e3..303d8ea224a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,11 +24,6 @@ using namespace chatterino; int main(int argc, char **argv) { - // TODO: This is a temporary fix (see #4552). -#if defined(Q_OS_WINDOWS) && QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - qputenv("QT_ENABLE_HIGHDPI_SCALING", "0"); -#endif - QApplication a(argc, argv); QCoreApplication::setApplicationName("chatterino"); diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index f69d0b785be..190b16e9418 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -208,8 +208,8 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container, { if (flags.has(MessageElementFlag::EmoteImages)) { - auto image = - this->emote_->images.getImageOrLoaded(container.getScale()); + auto image = this->emote_->images.getImageOrLoaded( + container.getImageScale()); if (image->isEmpty()) return; @@ -262,7 +262,7 @@ void LayeredEmoteElement::addToContainer(MessageLayoutContainer &container, { if (flags.has(MessageElementFlag::EmoteImages)) { - auto images = this->getLoadedImages(container.getScale()); + auto images = this->getLoadedImages(container.getImageScale()); if (images.empty()) { return; @@ -417,7 +417,7 @@ void BadgeElement::addToContainer(MessageLayoutContainer &container, if (flags.hasAny(this->getFlags())) { auto image = - this->emote_->images.getImageOrLoaded(container.getScale()); + this->emote_->images.getImageOrLoaded(container.getImageScale()); if (image->isEmpty()) return; @@ -691,7 +691,7 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container, { auto emote = boost::get(parsedWord); auto image = - emote->images.getImageOrLoaded(container.getScale()); + emote->images.getImageOrLoaded(container.getImageScale()); if (!image->isEmpty()) { auto emoteScale = getSettings()->emoteScale.getValue(); @@ -828,7 +828,7 @@ void ScalingImageElement::addToContainer(MessageLayoutContainer &container, if (flags.hasAny(this->getFlags())) { const auto &image = - this->images_.getImageOrLoaded(container.getScale()); + this->images_.getImageOrLoaded(container.getImageScale()); if (image->isEmpty()) return; diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index a2d961bdd0f..f6aab1ac1ce 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -74,7 +74,8 @@ int MessageLayout::getWidth() const // Layout // return true if redraw is required -bool MessageLayout::layout(int width, float scale, MessageElementFlags flags) +bool MessageLayout::layout(int width, float scale, float imageScale, + MessageElementFlags flags) { // BenchmarkGuard benchmark("MessageLayout::layout()"); @@ -106,6 +107,8 @@ bool MessageLayout::layout(int width, float scale, MessageElementFlags flags) // check if dpi changed layoutRequired |= this->scale_ != scale; this->scale_ = scale; + layoutRequired |= this->imageScale_ != imageScale; + this->imageScale_ = imageScale; if (!layoutRequired) { @@ -143,7 +146,8 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags) bool hideSimilar = getSettings()->hideSimilar; bool hideReplies = !flags.has(MessageElementFlag::RepliedMessage); - this->container_.beginLayout(width, this->scale_, messageFlags); + this->container_.beginLayout(width, this->scale_, this->imageScale_, + messageFlags); for (const auto &element : this->message_->elements) { @@ -280,16 +284,11 @@ QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width) } // Create new buffer -#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) this->buffer_ = std::make_unique( int(width * painter.device()->devicePixelRatioF()), int(this->container_.getHeight() * painter.device()->devicePixelRatioF())); this->buffer_->setDevicePixelRatio(painter.device()->devicePixelRatioF()); -#else - this->buffer_ = std::make_unique( - width, std::max(16, this->container_.getHeight())); -#endif this->bufferValid_ = false; DebugCount::increase("message drawing buffers"); diff --git a/src/messages/layouts/MessageLayout.hpp b/src/messages/layouts/MessageLayout.hpp index c4f0796a287..6fa20e4b608 100644 --- a/src/messages/layouts/MessageLayout.hpp +++ b/src/messages/layouts/MessageLayout.hpp @@ -52,7 +52,8 @@ class MessageLayout MessageLayoutFlags flags; - bool layout(int width, float scale_, MessageElementFlags flags); + bool layout(int width, float scale_, float imageScale_, + MessageElementFlags flags); // Painting void paint(const MessagePaintContext &ctx); @@ -105,6 +106,7 @@ class MessageLayout int currentLayoutWidth_ = -1; int layoutState_ = -1; float scale_ = -1; + float imageScale_ = -1.F; MessageElementFlags currentWordFlags_; #ifdef FOURTF diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index ec2995b7d72..b1c95b50604 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -30,7 +30,7 @@ constexpr const QMargins MARGIN{8, 4, 8, 4}; namespace chatterino { void MessageLayoutContainer::beginLayout(int width, float scale, - MessageFlags flags) + float imageScale, MessageFlags flags) { this->elements_.clear(); this->lines_.clear(); @@ -45,6 +45,7 @@ void MessageLayoutContainer::beginLayout(int width, float scale, this->width_ = width; this->height_ = 0; this->scale_ = scale; + this->imageScale_ = imageScale; this->flags_ = flags; auto mediumFontMetrics = getApp()->fonts->getFontMetrics(FontStyle::ChatMedium, scale); @@ -477,6 +478,11 @@ float MessageLayoutContainer::getScale() const return this->scale_; } +float MessageLayoutContainer::getImageScale() const +{ + return this->imageScale_; +} + bool MessageLayoutContainer::isCollapsed() const { return this->isCollapsed_; diff --git a/src/messages/layouts/MessageLayoutContainer.hpp b/src/messages/layouts/MessageLayoutContainer.hpp index 5887295fbdd..48598d2445d 100644 --- a/src/messages/layouts/MessageLayoutContainer.hpp +++ b/src/messages/layouts/MessageLayoutContainer.hpp @@ -32,7 +32,8 @@ struct MessageLayoutContainer { * This will reset all line calculations, and will be considered incomplete * until the accompanying end function has been called */ - void beginLayout(int width_, float scale_, MessageFlags flags_); + void beginLayout(int width, float scale, float imageScale, + MessageFlags flags); /** * Finish the layout process of this message @@ -131,6 +132,11 @@ struct MessageLayoutContainer { */ float getScale() const; + /** + * Returns the image scale + */ + float getImageScale() const; + /** * Returns true if this message is collapsed */ @@ -250,6 +256,10 @@ struct MessageLayoutContainer { // variables float scale_ = 1.F; + /** + * Scale factor for images + */ + float imageScale_ = 1.F; int width_ = 0; MessageFlags flags_{}; /** diff --git a/src/widgets/AttachedWindow.cpp b/src/widgets/AttachedWindow.cpp index acb00263bfe..158e20164a4 100644 --- a/src/widgets/AttachedWindow.cpp +++ b/src/widgets/AttachedWindow.cpp @@ -271,20 +271,22 @@ void AttachedWindow::updateWindowRect(void *_attachedPtr) } float scale = 1.f; + float ourScale = 1.F; if (auto dpi = getWindowDpi(attached)) { scale = dpi.get() / 96.f; + ourScale = scale / this->devicePixelRatio(); for (auto w : this->ui_.split->findChildren()) { - w->setOverrideScale(scale); + w->setOverrideScale(ourScale); } - this->ui_.split->setOverrideScale(scale); + this->ui_.split->setOverrideScale(ourScale); } if (this->height_ != -1) { - this->ui_.split->setFixedWidth(int(this->width_ * scale)); + this->ui_.split->setFixedWidth(int(this->width_ * ourScale)); // offset int o = this->fullscreen_ ? 0 : 8; diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 7fc1a3b53f5..eb9c5519d73 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -28,8 +28,6 @@ # pragma comment(lib, "Dwmapi.lib") # include - -# define WM_DPICHANGED 0x02E0 #endif #include "widgets/helper/TitlebarButton.hpp" @@ -199,13 +197,6 @@ void BaseWindow::init() this->ui_.layoutBase->setContentsMargins(1, 0, 1, 1); layout->addWidget(this->ui_.layoutBase); } - -// DPI -// auto dpi = getWindowDpi(this->winId()); - -// if (dpi) { -// this->scale = dpi.value() / 96.f; -// } #endif #ifdef USEWINSDK @@ -517,25 +508,8 @@ void BaseWindow::resizeEvent(QResizeEvent *) } #ifdef USEWINSDK - if (this->hasCustomWindowFrame() && !this->isResizeFixing_) - { - this->isResizeFixing_ = true; - QTimer::singleShot(50, this, [this] { - RECT rect; - ::GetWindowRect((HWND)this->winId(), &rect); - ::SetWindowPos((HWND)this->winId(), nullptr, 0, 0, - rect.right - rect.left + 1, rect.bottom - rect.top, - SWP_NOMOVE | SWP_NOZORDER); - ::SetWindowPos((HWND)this->winId(), nullptr, 0, 0, - rect.right - rect.left, rect.bottom - rect.top, - SWP_NOMOVE | SWP_NOZORDER); - QTimer::singleShot(10, this, [this] { - this->isResizeFixing_ = false; - }); - }); - } - this->calcButtonsSizes(); + this->updateRealSize(); #endif } @@ -576,10 +550,6 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, switch (msg->message) { - case WM_DPICHANGED: - returnValue = this->handleDPICHANGED(msg); - break; - case WM_SHOWWINDOW: returnValue = this->handleSHOWWINDOW(msg); break; @@ -650,6 +620,16 @@ void BaseWindow::updateScale() } } +#ifdef USEWINSDK +void BaseWindow::updateRealSize() +{ + RECT real; + ::GetWindowRect(HWND(this->winId()), &real); + this->realBounds_ = QRect(real.left, real.top, real.right - real.left, + real.bottom - real.top); +} +#endif + void BaseWindow::calcButtonsSizes() { if (!this->shown_) @@ -689,34 +669,16 @@ void BaseWindow::drawCustomWindowFrame(QPainter &painter) { QColor bg = this->overrideBackgroundColor_.value_or( this->theme->window.background); - painter.fillRect(QRect(1, 2, this->width() - 2, this->height() - 3), + // We want a border of [about] one pixel + auto invDpr = 1 / this->devicePixelRatio(); + painter.setTransform(QTransform::fromScale(invDpr, invDpr)); + painter.fillRect(QRect(1, 2, this->realBounds_.width() - 2, + this->realBounds_.height() - 3), bg); } #endif } -bool BaseWindow::handleDPICHANGED(MSG *msg) -{ -#ifdef USEWINSDK - int dpi = HIWORD(msg->wParam); - - float _scale = dpi / 96.f; - - auto *prcNewWindow = reinterpret_cast(msg->lParam); - SetWindowPos(msg->hwnd, nullptr, prcNewWindow->left, prcNewWindow->top, - prcNewWindow->right - prcNewWindow->left, - prcNewWindow->bottom - prcNewWindow->top, - SWP_NOZORDER | SWP_NOACTIVATE); - - this->nativeScale_ = _scale; - this->updateScale(); - - return true; -#else - return false; -#endif -} - bool BaseWindow::handleSHOWWINDOW(MSG *msg) { #ifdef USEWINSDK @@ -726,16 +688,6 @@ bool BaseWindow::handleSHOWWINDOW(MSG *msg) return true; } - if (auto dpi = getWindowDpi(msg->hwnd)) - { - float currentScale = (float)dpi.get() / 96.F; - if (currentScale != this->nativeScale_) - { - this->nativeScale_ = currentScale; - this->updateScale(); - } - } - if (!this->shown_) { this->shown_ = true; @@ -749,14 +701,12 @@ bool BaseWindow::handleSHOWWINDOW(MSG *msg) if (!this->initalBounds_.isNull()) { - ::SetWindowPos(msg->hwnd, nullptr, this->initalBounds_.x(), - this->initalBounds_.y(), this->initalBounds_.width(), - this->initalBounds_.height(), - SWP_NOZORDER | SWP_NOACTIVATE); + this->setGeometry(this->initalBounds_); this->currentBounds_ = this->initalBounds_; } this->calcButtonsSizes(); + this->updateRealSize(); } return true; @@ -807,11 +757,7 @@ bool BaseWindow::handleSIZE(MSG *msg) { if (msg->wParam == SIZE_MAXIMIZED) { - auto offset = int( - getWindowDpi(HWND(this->winId())).value_or(96) * 8 / 96); - - this->ui_.windowLayout->setContentsMargins(offset, offset, - offset, offset); + this->ui_.windowLayout->setContentsMargins(8, 8, 8, 8); } else { @@ -822,13 +768,15 @@ bool BaseWindow::handleSIZE(MSG *msg) if (this->isNotMinimizedOrMaximized_) { - RECT rect; - ::GetWindowRect(msg->hwnd, &rect); - this->currentBounds_ = - QRect(QPoint(rect.left, rect.top), - QPoint(rect.right - 1, rect.bottom - 1)); + this->currentBounds_ = this->geometry(); } this->useNextBounds_.stop(); + + RECT real; + ::GetWindowRect(msg->hwnd, &real); + this->realBounds_ = + QRect(real.left, real.top, real.right - real.left, + real.bottom - real.top); } } return false; @@ -842,11 +790,7 @@ bool BaseWindow::handleMOVE(MSG *msg) #ifdef USEWINSDK if (this->isNotMinimizedOrMaximized_) { - RECT rect; - ::GetWindowRect(msg->hwnd, &rect); - this->nextBounds_ = QRect(QPoint(rect.left, rect.top), - QPoint(rect.right - 1, rect.bottom - 1)); - + this->nextBounds_ = this->geometry(); this->useNextBounds_.start(10); } #endif @@ -860,7 +804,7 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result) #endif { #ifdef USEWINSDK - const LONG border_width = 8; // in pixels + const LONG borderWidth = 8; // in pixels RECT winrect; GetWindowRect(HWND(winId()), &winrect); @@ -868,6 +812,7 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result) long y = GET_Y_LPARAM(msg->lParam); QPoint point(x - winrect.left, y - winrect.top); + point /= this->devicePixelRatio(); if (this->hasCustomWindowFrame()) { @@ -879,12 +824,12 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result) if (resizeWidth) { // left border - if (x < winrect.left + border_width) + if (x < winrect.left + borderWidth) { *result = HTLEFT; } // right border - if (x >= winrect.right - border_width) + if (x >= winrect.right - borderWidth) { *result = HTRIGHT; } @@ -892,12 +837,12 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result) if (resizeHeight) { // bottom border - if (y >= winrect.bottom - border_width) + if (y >= winrect.bottom - borderWidth) { *result = HTBOTTOM; } // top border - if (y < winrect.top + border_width) + if (y < winrect.top + borderWidth) { *result = HTTOP; } @@ -905,26 +850,26 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result) if (resizeWidth && resizeHeight) { // bottom left corner - if (x >= winrect.left && x < winrect.left + border_width && - y < winrect.bottom && y >= winrect.bottom - border_width) + if (x >= winrect.left && x < winrect.left + borderWidth && + y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMLEFT; } // bottom right corner - if (x < winrect.right && x >= winrect.right - border_width && - y < winrect.bottom && y >= winrect.bottom - border_width) + if (x < winrect.right && x >= winrect.right - borderWidth && + y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMRIGHT; } // top left corner - if (x >= winrect.left && x < winrect.left + border_width && - y >= winrect.top && y < winrect.top + border_width) + if (x >= winrect.left && x < winrect.left + borderWidth && + y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPLEFT; } // top right corner - if (x < winrect.right && x >= winrect.right - border_width && - y >= winrect.top && y < winrect.top + border_width) + if (x < winrect.right && x >= winrect.right - borderWidth && + y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPRIGHT; } diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp index 864e8f9bf9c..5eb47eef5a3 100644 --- a/src/widgets/BaseWindow.hpp +++ b/src/widgets/BaseWindow.hpp @@ -104,7 +104,6 @@ class BaseWindow : public BaseWidget void drawCustomWindowFrame(QPainter &painter); void onFocusLost(); - bool handleDPICHANGED(MSG *msg); bool handleSHOWWINDOW(MSG *msg); bool handleSIZE(MSG *msg); bool handleMOVE(MSG *msg); @@ -122,7 +121,6 @@ class BaseWindow : public BaseWidget bool shown_ = false; FlagsEnum flags_; float nativeScale_ = 1; - bool isResizeFixing_ = false; struct { QLayout *windowLayout = nullptr; @@ -136,11 +134,16 @@ class BaseWindow : public BaseWidget } ui_; #ifdef USEWINSDK + void updateRealSize(); + QRect initalBounds_; QRect currentBounds_; QRect nextBounds_; QTimer useNextBounds_; bool isNotMinimizedOrMaximized_{}; + /// The real bounds of the window as returned by + /// GetWindowRect. + QRect realBounds_; #endif pajlada::Signals::SignalHolder connections_; diff --git a/src/widgets/Label.cpp b/src/widgets/Label.cpp index 7f5e8a4ce80..93a40d5e77e 100644 --- a/src/widgets/Label.cpp +++ b/src/widgets/Label.cpp @@ -85,21 +85,9 @@ void Label::paintEvent(QPaintEvent *) { QPainter painter(this); - qreal deviceDpi = -#ifdef Q_OS_WIN - this->devicePixelRatioF(); -#else - 1.0; -#endif - - QFontMetrics metrics = getFonts()->getFontMetrics( - this->getFontStyle(), - this->scale() * 96.f / - std::max(0.01, this->logicalDpiX() * deviceDpi)); - painter.setFont(getFonts()->getFont( - this->getFontStyle(), - this->scale() * 96.f / - std::max(0.02, this->logicalDpiX() * deviceDpi))); + QFontMetrics metrics = + getFonts()->getFontMetrics(this->getFontStyle(), this->scale()); + painter.setFont(getFonts()->getFont(this->getFontStyle(), this->scale())); int offset = this->getOffset(); diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index 1ee94b4cfea..d7750454d1d 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -41,12 +41,16 @@ SettingsDialog::SettingsDialog(QWidget *parent) this->resize(915, 600); this->themeChangedEvent(); - this->scaleChangedEvent(this->scale()); + QFile styleFile(":/qss/settings.qss"); + styleFile.open(QFile::ReadOnly); + QString stylesheet = QString::fromUtf8(styleFile.readAll()); + this->setStyleSheet(stylesheet); this->initUi(); this->addTabs(); this->overrideBackgroundColor_ = QColor("#111111"); - this->scaleChangedEvent(this->scale()); // execute twice to width of item + this->scaleChangedEvent(this->scale()); + this->scaleChangedEvent(this->scale()); this->addShortcuts(); this->signalHolder_.managedConnect(getApp()->hotkeys->onItemsUpdated, @@ -354,21 +358,19 @@ void SettingsDialog::refresh() void SettingsDialog::scaleChangedEvent(float newDpi) { - QFile file(":/qss/settings.qss"); - file.open(QFile::ReadOnly); - QString styleSheet = QLatin1String(file.readAll()); - styleSheet.replace("", QString::number(int(14 * newDpi))); - styleSheet.replace("", QString::number(int(14 * newDpi))); + Q_ASSERT_X(newDpi == 1.F, Q_FUNC_INFO, + "Scaling is disabled for the settings dialog - its scale should " + "always be 1"); for (SettingsDialogTab *tab : this->tabs_) { - tab->setFixedHeight(int(30 * newDpi)); + tab->setFixedHeight(30); } - this->setStyleSheet(styleSheet); - if (this->ui_.tabContainerContainer) - this->ui_.tabContainerContainer->setFixedWidth(int(150 * newDpi)); + { + this->ui_.tabContainerContainer->setFixedWidth(150); + } } void SettingsDialog::themeChangedEvent() diff --git a/src/widgets/helper/Button.cpp b/src/widgets/helper/Button.cpp index b4caa299f77..da969a028f8 100644 --- a/src/widgets/helper/Button.cpp +++ b/src/widgets/helper/Button.cpp @@ -8,22 +8,44 @@ #include #include -namespace chatterino { namespace { - // returns a new resized image or the old one if the size didn't change - auto resizePixmap(const QPixmap ¤t, const QPixmap resized, - const QSize &size) -> QPixmap +QSizeF deviceIndependentSize(const QPixmap &pixmap) +{ +#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0) + return pixmap.size().toSizeF() / pixmap.devicePixelRatio(); +#else + return pixmap.deviceIndependentSize(); +#endif +} + +/** + * Resizes a pixmap to a desired size. + * Does nothing if the target pixmap is already sized correctly. + * + * @param target The target pixmap. + * @param source The unscaled pixmap. + * @param size The desired device independent size. + * @param dpr The device pixel ratio of the target area. The size of the target in pixels will be `size * dpr`. + */ +void resizePixmap(QPixmap &target, const QPixmap &source, const QSize &size, + qreal dpr) +{ + if (deviceIndependentSize(target) == size) { - if (resized.size() == size) - return resized; - else - return current.scaled(size, Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); + return; } + QPixmap resized = source; + resized.setDevicePixelRatio(dpr); + target = resized.scaled(size * dpr, Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); +} + } // namespace +namespace chatterino { + Button::Button(BaseWidget *parent) : BaseWidget(parent) { @@ -43,6 +65,12 @@ void Button::setMouseEffectColor(boost::optional color) void Button::setPixmap(const QPixmap &_pixmap) { + // Avoid updates if the pixmap didn't change + if (_pixmap.cacheKey() == this->pixmap_.cacheKey()) + { + return; + } + this->pixmap_ = _pixmap; this->resizedPixmap_ = {}; this->update(); @@ -146,8 +174,8 @@ void Button::paintButton(QPainter &painter) QRect rect = this->rect(); - this->resizedPixmap_ = - resizePixmap(this->pixmap_, this->resizedPixmap_, rect.size()); + resizePixmap(this->resizedPixmap_, this->pixmap_, rect.size(), + this->devicePixelRatio()); int margin = this->height() < 22 * this->scale() ? 3 : 6; diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 3d1924e8617..eb218d05b4a 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -486,8 +486,9 @@ void ChannelView::layoutVisibleMessages( { const auto &message = messages[i]; - redrawRequired |= - message->layout(layoutWidth, this->scale(), flags); + redrawRequired |= message->layout( + layoutWidth, this->scale(), + this->scale() * this->devicePixelRatio(), flags); y += message->getHeight(); } @@ -520,7 +521,8 @@ void ChannelView::updateScrollbar( { auto *message = messages[i].get(); - message->layout(layoutWidth, this->scale(), flags); + message->layout(layoutWidth, this->scale(), + this->scale() * this->devicePixelRatio(), flags); h -= message->getHeight(); @@ -1420,8 +1422,10 @@ void ChannelView::wheelEvent(QWheelEvent *event) } else { - snapshot[i - 1]->layout(this->getLayoutWidth(), - this->scale(), this->getFlags()); + snapshot[i - 1]->layout( + this->getLayoutWidth(), this->scale(), + this->scale() * this->devicePixelRatio(), + this->getFlags()); scrollFactor = 1; currentScrollLeft = snapshot[i - 1]->getHeight(); } @@ -1454,8 +1458,10 @@ void ChannelView::wheelEvent(QWheelEvent *event) } else { - snapshot[i + 1]->layout(this->getLayoutWidth(), - this->scale(), this->getFlags()); + snapshot[i + 1]->layout( + this->getLayoutWidth(), this->scale(), + this->scale() * this->devicePixelRatio(), + this->getFlags()); scrollFactor = 1; currentScrollLeft = snapshot[i + 1]->getHeight(); diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 297ccf19b29..c8e1317a1c3 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -27,15 +27,6 @@ namespace chatterino { namespace { - qreal deviceDpi(QWidget *widget) - { -#ifdef Q_OS_WIN - return widget->devicePixelRatioF(); -#else - return 1.0; -#endif - } - // Translates the given rectangle by an amount in the direction to appear like the tab is selected. // For example, if location is Top, the rectangle will be translated in the negative Y direction, // or "up" on the screen, by amount. @@ -196,8 +187,8 @@ int NotebookTab::normalTabWidth() float scale = this->scale(); int width; - QFontMetrics metrics = getApp()->fonts->getFontMetrics( - FontStyle::UiTabs, float(qreal(this->scale()) * deviceDpi(this))); + QFontMetrics metrics = + getApp()->fonts->getFontMetrics(FontStyle::UiTabs, this->scale()); if (this->hasXButton()) { @@ -414,11 +405,8 @@ void NotebookTab::paintEvent(QPaintEvent *) QPainter painter(this); float scale = this->scale(); - auto div = std::max(0.01f, this->logicalDpiX() * deviceDpi(this)); - painter.setFont( - getApp()->fonts->getFont(FontStyle::UiTabs, scale * 96.f / div)); - QFontMetrics metrics = - app->fonts->getFontMetrics(FontStyle::UiTabs, scale * 96.f / div); + painter.setFont(getApp()->fonts->getFont(FontStyle::UiTabs, scale)); + QFontMetrics metrics = app->fonts->getFontMetrics(FontStyle::UiTabs, scale); int height = int(scale * NOTEBOOK_TAB_HEIGHT);