Skip to content

POC: Wayland fractional scale support#30492

Draft
zvova7890 wants to merge 1 commit intotelegramdesktop:devfrom
zvova7890:wayland-fractional-scale-support
Draft

POC: Wayland fractional scale support#30492
zvova7890 wants to merge 1 commit intotelegramdesktop:devfrom
zvova7890:wayland-fractional-scale-support

Conversation

@zvova7890
Copy link
Copy Markdown

@zvova7890 zvova7890 commented Mar 30, 2026

Since Telegram moved to Qt6, it has broken fractional scaling support on both X11 and Wayland. With Qt5, fractional scaling works as usual on X11. So I rebuilt Telegram myself with patches that force XWayland and built it with Qt5, thus fixing recurring compilation issues with new code.

Lately, I was wondering if current AI capabilities would be enough to fix the infamous "unfixable" Telegram problem? Apparently, yes! Just throw in an idea and see the magic. If nobody wants to fix it, let AI do it, right?

Anyway, after a ~day of iterations and fixing crashes/glitches/etc., I ended up with a patch that allows Telegram to run with a crystal-clear picture under a KDE Wayland session with 1.5 and 2.5 scale factors. Even enabling experimental fractional scaling works as intended.

There are still crashes/glitches/hangs because many places are not obviously dependent on the DevicePixelRatio. All usages of DevicePixelRatio should be reviewed, but there is a lot of code, and this can be done gradually, as ideally these changes should not break integer scaling. For example, I spent an hour figuring out why the user profile image history was trying to load images infinitely with no success. It turned out there was a check like if (target.size() == requested) cached = true; and computation just don't match because of fractional scale.

So basically, I don’t think anyone would be interested in merging this. Moreover, I don’t think I want to make it production-ready. I’m just sharing this as a proof of concept that says "Hey, it’s possible".

About 98% of the refactoring/bug fixing was done by GPT 5.4. I’m familiar with Qt, but not with the Telegram codebase at all. AI just makes it 9999x faster. God bless RAM.

There are also parts in lib_ui and lib_lottie; I’ve included the diff here if anyone wants to check it out.

Feel free to close this PR at any time!

tg-fraction-scale.diff.tar.gz diff for v6.6.4

image image

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 30, 2026

CLA assistant check
All committers have signed the CLA.

if (Platform::IsMac()) {
// 110% for Retina screens by default.
cSetScreenScale((useRatio == 2) ? 110 : style::kScaleDefault);
cSetScreenScale((useRatio >= 1.99) ? 110 : style::kScaleDefault);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do you change this macOS-specific code?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Artefact, never mind

@ilya-fedin
Copy link
Copy Markdown
Contributor

If I understand right, style::DevicePixelRatio is still set from QGuiApplication::devicePixelRatio? But AFAIK it returns ceiled value on fractional scales, how does it work?

@zvova7890
Copy link
Copy Markdown
Author

If I understand right, style::DevicePixelRatio is still set from QGuiApplication::devicePixelRatio? But AFAIK it returns ceiled value on fractional scales, how does it work?

Yes, but not exactly. It is updated later in RefreshDevicePixelRatioFromWindow when QWindow receives a new scale factor from the compositor. Because of that, Telegram should support dynamically changing the scale at runtime. There were several problems with that, which I found during testing -- all known ones were resolved. Actually, it should be connected to QWindow::screenChanged and update the scale factor every time it changes. In that case, if the scale factor changes due to a monitor settings update or the window moving to another screen with a different scale factor, the UI will stay crisp. In this diff it is not yet done, but on my local branch I've already tested -- it seems to be working fine.

@ilya-fedin
Copy link
Copy Markdown
Contributor

Actually, it should be connected to QWindow::screenChanged and update the scale factor every time it changes.

That's not really right since on Wayland fractional scale factor is per-window rather than per-screen. The right event is QEvent::DevicePixelRatioChange.

RefreshDevicePixelRatioFromWindow

I don't see it in this PR 🤔

@zvova7890
Copy link
Copy Markdown
Author

That's not really right since on Wayland fractional scale factor is per-window rather than per-screen. The right event is QEvent::DevicePixelRatioChange.

Yes, you're right. Despite Qt still sending screenChanged events on Wayland for per‑window fractional scale changes, probably because all other platforms do that and Qt wants to keep as much as possible the same behavior across platforms, DevicePixelRatioChange is a better choice.

I don't see it in this PR 🤔

https://github.com/telegramdesktop/tdesktop/pull/30492/changes#diff-fb20cd304b852c78660103605c2f357ddfd811e2a29a5260731974e38817f923R84


BTW, AFAIK Telegram does not support dynamic scale change on all platforms, right? I was interested whether it was possible even theoretically, and it seems yes, I managed to make core UI functionality adapt dynamically to the scale changes (e.g. moving around monitors with different scales or changing the scale for one monitor). Oh, how many caches, so many caches... There is the cache even for rounded rects :)

@ilya-fedin
Copy link
Copy Markdown
Contributor

https://github.com/telegramdesktop/tdesktop/pull/30492/changes#diff-fb20cd304b852c78660103605c2f357ddfd811e2a29a5260731974e38817f923R84

Oh, thanks

BTW, AFAIK Telegram does not support dynamic scale change on all platforms, right? I was interested whether it was possible even theoretically, and it seems yes, I managed to make core UI functionality adapt dynamically to the scale changes (e.g. moving around monitors with different scales or changing the scale for one monitor). Oh, how many caches, so many caches... There is the cache even for rounded rects :)

Yeah, the fact that the app has lots of cache for CPU-based animations is the main blocker to support runtime scale changes and implement #1121. I so far believed that it's an architectural choice that couldn't be fixed at that point in time and only new client written from scratch on some other toolkit could fix it (such as https://web.telegram.org/a/get).

@zvova7890 zvova7890 force-pushed the wayland-fractional-scale-support branch from 2d0d1f5 to 3b794c5 Compare April 2, 2026 18:22
@zvova7890 zvova7890 force-pushed the wayland-fractional-scale-support branch from 3b794c5 to e9b1ed2 Compare April 2, 2026 18:32
@zvova7890
Copy link
Copy Markdown
Author

I've pushed an updated version, with initial dynamic DPR support. So far, what I'm using works +- fine. I think it pretty doable 🤔

@ilya-fedin
Copy link
Copy Markdown
Contributor

I've pushed an updated version, with initial dynamic DPR support. So far, what I'm using works +- fine.

It conflicts though...

@zvova7890
Copy link
Copy Markdown
Author

It conflicts though...

That's because I'm on v6.6.4, not a head

@Azq2
Copy link
Copy Markdown

Azq2 commented Apr 3, 2026

Great thanks, you save my eyes

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.

4 participants