Re: Decreasing seams in scaled windows
John Ehresman <[email protected]> Mon, 22 Jun 2026 21:19:46 +0100
| Newsgroups | gmane.comp.lib.scintilla.devel |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail=_923E9008-7E22-4697-94D5-DA496923509C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" The problem was that the upper left of the widget needs to be taken into ac= count when snapping the rectangle. Here=E2=80=99s a revised patch based of = what I sent previously (I can rearrange functions if you want). It does get= the scale factor from the environment, which should probably be reworked = =E2=80=94 the issue is that Qt doesn=E2=80=99t expose it in its api that I = know of and the Wayland=E2=80=99s magnification factor isn=E2=80=99t fixed = at 2 like the factor for macOS retina displays. I=E2=80=99ve only tested lightly on Wayland. John --=20 You received this message because you are subscribed to the Google Groups "= scintilla-interest" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/scintilla-i= nterest/0F55D014-CF08-4085-94C9-CF7D66E4EEB3%40wingware.com. --Apple-Mail=_923E9008-7E22-4697-94D5-DA496923509C Content-Disposition: attachment; filename=QtScale-PlatQt2.patch Content-Type: application/octet-stream; x-unix-mode=0664; name="QtScale-PlatQt2.patch" Content-Transfer-Encoding: 7bit --- a/qt/ScintillaEditBase/PlatQt.cpp +++ b/qt/ScintillaEditBase/PlatQt.cpp @@ -223,6 +223,55 @@ return variant.toDouble(); } +// Define SCINTILLA_QT_BACKINGSTORE_FIXED when building against a Qt whose +// backing store tracks dirty state at device-pixel resolution; that makes the +// fractional-scaling workarounds below compile out entirely. + +#if !defined(Q_OS_WIN) && !defined(SCINTILLA_QT_BACKINGSTORE_FIXED) +// Grow a logical update rect so its edges land on whole native pixels, in window +// coordinates (Qt rounds the dirty region there, so the widget's offset is applied). +static QRect SnapToNativeWindowPixelGrid(QWidget *widget, QRect upd) +{ + if (!widget) + return upd; + const qreal winDpr = widget->devicePixelRatioF(); + double guiFactor = 0.0; + const QByteArray sf = qgetenv("QT_SCALE_FACTOR"); + if (!sf.isEmpty()) { + bool ok = false; + const double v = sf.toDouble(&ok); + if (ok && v > 0.0) + guiFactor = v; + } + if (guiFactor <= 0.0) + return (winDpr == std::floor(winDpr)) ? upd : QRect(); + + int q = 0; + for (int n = 1; n <= 64; ++n) { + if (std::fabs(guiFactor * n - std::round(guiFactor * n)) < 1e-4) { + q = n; + break; + } + } + if (q == 0) + return QRect(); + if (q == 1) + return upd; + + const QPoint off = widget->mapTo(widget->window(), QPoint(0, 0)); + auto floorTo = [q](int v) { int r = v % q; if (r < 0) r += q; return v - r; }; + const int l = floorTo(upd.left() + off.x()) - off.x(); + const int t = floorTo(upd.top() + off.y()) - off.y(); + const int r = floorTo(upd.right() + 1 + off.x() + q - 1) - off.x(); + const int b = floorTo(upd.bottom() + 1 + off.y() + q - 1) - off.y(); + const QRect snapped(QPoint(l, t), QPoint(r - 1, b - 1)); + const QSize widgetSize = widget->size(); + if (snapped.width() >= widgetSize.width() && snapped.height() >= widgetSize.height()) + return QRect(); + return snapped; +} +#endif + double ScaleToMultiply(WindowID wid) { const qreal scale = ScaleOfWindow(wid); @@ -934,18 +983,28 @@ { if (wid) { const qreal scale = ScaleOfWindow(wid); - if (scale) { -#if !defined(Q_OS_WIN) && !defined(Q_OS_APPLE) - // Using X11 or Wayland, likely Linux but may be a BSD or similar - if (scale != 1.0 && scale != 2.0) { - // Fractional scaling leaves repaint debris, so redraw completely + QRect upd; + + if (!scale) { + upd = QRectFromPRect(rc); + } + else { + upd = QRectFFromPRect(rc / scale).toAlignedRect(); + +#if !defined(Q_OS_WIN) && !defined(SCINTILLA_QT_BACKINGSTORE_FIXED) + // Snap to whole native pixels to avoid the fractional-scale backing-store + // seam; a null result means a full redraw is needed. + const QRect snapped = + SnapToNativeWindowPixelGrid(window(wid), upd); + if (snapped.isNull()) { window(wid)->update(); return; } + upd = snapped; #endif - rc = rc / scale; } - window(wid)->update(QRectFromPRect(rc)); + + window(wid)->update(upd); } } --Apple-Mail=_923E9008-7E22-4697-94D5-DA496923509C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" =20 > On Jun 22, 2026, at 12:18=E2=80=AFPM, John Ehresman <[email protected]> wr= ote: >=20 > Neil, >=20 > Wayland has a similar dirty region bug and I have a local patch to fix it= . It=E2=80=99s a Qt bug =E2=80=94 I see more debris lines in the list widge= t and menus more than I do in scintilla. But the snap workaround doesn=E2= =80=99t seem to fix it and I=E2=80=99m trying to figure out why. >=20 > I see the debris on Wayland when the display magnification is 200% and I = add a Qt scale factor of 1.5 (or other) on top of that, but I was unable to= see debris with a display magnification of 100%. What display magnificatio= n are you using? >=20 > Thanks, >=20 > John >=20 >> On Jun 21, 2026, at 12:21=E2=80=AFAM, Neil Hodgson <scintilladotorg@gmai= l.com> wrote: >>=20 >> John: >>=20 >>> Here=E2=80=99s a version that always snaps. >>=20 >> That worked for me on macOS. >>=20 >>> The backing store has a grid of what is dirty and that grid is only hal= f the size of the backing store on retina displays. Making it full size see= ms to fix the one pixel lines. >>=20 >> The Wayland/Linux lines may be a similar bug. Using the snap code >> (with changes to ensure it runs) fixes some cases but not others. It >> appears to fix 125% and 133% but not 150%. For 150% the problem moves >> a little - likely a single pixel. >> https://www.scintilla.org/QtScaleSnap150Wayland.png >>=20 >> To get this for 150% (with Ubuntu 26.04 LTS Wayland Qt 6.10.2 inside >> VirtualBox): >> * Disable the `if defined(Q_OS_APPLE)` checks >> * Remove the `if (backing =3D=3D 1)` checks since there is no 'retina' >> pixel-doubling >> * Remove the early return for scales other than 1.0 and 2.0 in >> InvalidateRectangle >>=20 >> This produces the expected 'q' of 2 (150%), 3 (133%), and 4 (125%) and >> the corresponding snapped rectangle value. >>=20 >> Neil >>=20 >> --=20 >> You received this message because you are subscribed to the Google Group= s "scintilla-interest" group. >> To unsubscribe from this group and stop receiving emails from it, send a= n email to [email protected]. >> To view this discussion visit https://groups.google.com/d/msgid/scintill= a-interest/CACWkrTiX45E9qpTcUezPOyDHwDOi8oCbCirY0JnAAFwSkY5faA%40mail.gmail= .com. >> <EnableSnap.patch> --=20 You received this message because you are subscribed to the Google Groups "= scintilla-interest" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/scintilla-i= nterest/0F55D014-CF08-4085-94C9-CF7D66E4EEB3%40wingware.com. --Apple-Mail=_923E9008-7E22-4697-94D5-DA496923509C--