Skip to content

Fix note list rendering at fractional display scaling#769

Open
Shriram-Vasudevan wants to merge 2 commits into
nuttyartist:masterfrom
Shriram-Vasudevan:fix-164-note-list-dpi-scaling
Open

Fix note list rendering at fractional display scaling#769
Shriram-Vasudevan wants to merge 2 commits into
nuttyartist:masterfrom
Shriram-Vasudevan:fix-164-note-list-dpi-scaling

Conversation

@Shriram-Vasudevan
Copy link
Copy Markdown

Summary

  • set Qt high-DPI scale factor rounding to pass through before creating the application
  • create note-list delegate paint buffers with the owning widget/window device-pixel ratio
  • use logical buffer geometry while painting cropped row backgrounds/labels, so Windows fractional scaling does not mix physical pixmap pixels with logical item rects

Fixes #164.

Verification

  • git diff --check
  • c++ -std=c++17 -fsyntax-only -include arm_acle.h ... src/notelistdelegate.cpp src/notelistdelegateeditor.cpp against locally installed Qt 6.9.2 headers
  • syntax-only check for QGuiApplication::setHighDpiScaleFactorRoundingPolicy(...) against Qt 6.9.2 headers

I could not run the full CMake build locally because cmake is not installed in this environment, and clang-format is also unavailable locally.

@zjeffer
Copy link
Copy Markdown
Collaborator

zjeffer commented May 11, 2026

@nuttyartist Do we have an AI-policy? Personally I'm not a big fan of these fully AI-generated PRs, I mean the OP didn't even bother to let the AI install cmake:

I could not run the full CMake build locally because cmake is not installed in this environment, and clang-format is also unavailable locally.

I recently added one in a personal repo if you want an example: https://github.com/zjeffer/split-monitor-workspaces/blob/main/CONTRIBUTING.md

@Shriram-Vasudevan
Copy link
Copy Markdown
Author

I installed the missing local build tooling and pushed follow-up commit 404e7cf with the clang-format adjustments found by the repo format gate.

Verification now run locally:

  • /opt/homebrew/opt/llvm/bin/clang-format -style=file --dry-run --Werror --color=false src/main.cpp src/notelistdelegate.cpp src/notelistdelegateeditor.cpp src/utils.h -> passed
  • find src/ -iregex '.*\.\(cpp\|h\|mm\)$' -print0 | xargs -n 1 -0 /opt/homebrew/opt/llvm/bin/clang-format -style=file --dry-run --Werror --color=false -> passed
  • cmake . --warn-uninitialized --warn-unused-vars -G Ninja -B build -DCMAKE_BUILD_TYPE=debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)" -DPRO_VERSION=OFF -> passed with Qt 6.9.2
  • cmake --build build -> passed
  • ctest --test-dir build --output-on-failure -> no tests registered
  • git diff --check -> passed

The build produced only existing/project-wide Qt deprecation and macOS deployment-target linker warnings, not errors in the touched note-list files.

Copy link
Copy Markdown
Owner

@nuttyartist nuttyartist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix. I left a few inline suggestions for the remaining DPR source-rect issue. The helper approach looks good; the main thing is making the later drawPixmap source rectangles use the same coordinate space as the DPR pixmaps.

Comment thread src/utils.h
#include <cmath>
#include <QString>
#include <QDateTime>
#include <QPixmap>
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper will also need QRect for converting logical source rects to pixmap/device-pixel source rects.

Suggested change
#include <QPixmap>
#include <QPixmap>
#include <QRect>

Comment thread src/utils.h
Comment on lines +69 to +75
inline QPixmap makeDevicePixelRatioPixmap(const QSize &logicalSize, const QWidget *widget)
{
const qreal scale = devicePixelRatioForWidget(widget);
QPixmap pixmap(logicalSize * scale);
pixmap.setDevicePixelRatio(scale);
return pixmap;
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we pair the DPR pixmap allocator with a small source-rect conversion helper? Painting into the pixmap stays in logical coordinates, but QPainter::drawPixmap(..., sourceRect) reads sourceRect in pixmap/device pixels.

Suggested change
inline QPixmap makeDevicePixelRatioPixmap(const QSize &logicalSize, const QWidget *widget)
{
const qreal scale = devicePixelRatioForWidget(widget);
QPixmap pixmap(logicalSize * scale);
pixmap.setDevicePixelRatio(scale);
return pixmap;
}
inline QPixmap makeDevicePixelRatioPixmap(const QSize &logicalSize, const QWidget *widget)
{
const qreal scale = devicePixelRatioForWidget(widget);
QPixmap pixmap(logicalSize * scale);
pixmap.setDevicePixelRatio(scale);
return pixmap;
}
inline QRect devicePixelRatioPixmapSourceRect(const QRect &logicalRect, const QPixmap &pixmap)
{
const qreal scale = pixmap.devicePixelRatio();
const QRectF scaledRect(logicalRect.x() * scale, logicalRect.y() * scale, logicalRect.width() * scale, logicalRect.height() * scale);
return scaledRect.toAlignedRect();
}

Comment thread src/notelistdelegate.cpp
{
auto bufferSize = bufferSizeHint(option, index);
QPixmap buffer{ bufferSize };
QPixmap buffer = utils::makeDevicePixelRatioPixmap(bufferSize, m_view);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once this buffer is DPR-aware, the drawPixmap(..., buffer, QRect{...}) calls lower in paintBackground() still need to convert their source rects before drawing. One compact way is to add this near the draw section and route those calls through it:

auto drawBuffer = [&buffer, painter](const QRect &targetRect, const QRect &sourceRect) {
    painter->drawPixmap(targetRect, buffer, utils::devicePixelRatioPixmapSourceRect(sourceRect, buffer));
};

Then replace each painter->drawPixmap(..., buffer, QRect{...}) in this function with drawBuffer(..., QRect{...}). The same pattern applies to the animated label buffer in paintLabels().

{
auto bufferSize = rect().size();
QPixmap buffer{ bufferSize };
QPixmap buffer = utils::makeDevicePixelRatioPixmap(bufferSize, this);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same coordinate-space issue here: the buffer is now DPR-aware, but the later source rect passed to drawPixmap() is still logical. The final draw should convert that source rect first, for example:

auto rowHeight = rect().height();
const QRect sourceRect{ 0, bufferSize.height() - rowHeight, rect().width(), rowHeight };
painter->drawPixmap(rect(), buffer, utils::devicePixelRatioPixmapSourceRect(sourceRect, buffer));

@nuttyartist
Copy link
Copy Markdown
Owner

@zjeffer Not really yet, and I agree, we should have. Yours seems reasonable enough, I'll add them to the repo.

@Shriram-Vasudevan Thanks for your PR.
I've added some comments using GPT 5.5, please look at them.
Can you please share before and after screenshots after you make changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug - notes are not aligned well on some reported Windows machines [$80]

3 participants