Decreasing seams in scaled windows

155 views
Skip to first unread message

Neil

unread,
Mar 4, 2026, 1:08:24 AMMar 4
to scintilla-interest
In some circumstances, when a Scintilla window is scaled by a fractional amount like 1.5x or 1.25x, visual anomalies occur between filled rectangles. The window background may show through because the rectangles before and after or above and below only partially draw shared pixels.

This can be seen in this image with Qt 6 on Win32 with 1.25x scaling.

This was reported in some bug tracker issues and in the "Scintilla GTK 4 port" thread.
In that thread, a couple of patches decrease the severity of the seams but do not eliminate them.

I believe the highest quality output will be produced when Scintilla is drawing to raw screen pixels and the text is scaled to match the window scaling factor. However, some platforms may make this difficult or impossible to accomplish so some improvements can be made.

[Overdraw by 1 pixel]

One technique to cover seams is to draw more than required to ensure that each pixel is completely covered by at least one filled rectangle call. Extending the area of each opaque background rectangle by 1 (logical) pixel horizontally and vertically can achieve this. Almost all background drawing occurs left-to-right & top-to-bottom, so each of these oversized rectangles will then have a following rectangle merge nicely on its leading pixel as it will only see the colour of the preceding rectangle, with no trace of the window background.

If the scaling factor is less than 1.0x (0.5x?), a larger extension may be needed.

This technique improves over the proposal to clear the whole window to a global background colour as it will work better with areas (like JavaScript in a HTML page) that use a different background colour.

There are problems with extending this to translucent drawing as a translucent drawing call will have different results when performed more times.

An incomplete implementation of this is available from

The results can be seen with the same text as above.
There are faint seams in the selection as it uses translucency and these will be more prominent when the selection colour differs more from the text background. There is a vertical seam between the line number and marker margins as the implementation is currently only for EditView. 

This code is slower and could potentially cause flicker due to drawing some pixels multiple times. It only works in unbuffered mode and with SCI_SETPHASESDRAW(SC_PHASES_MULTIPLE) since it draws outside the strict line rectangles used in other modes.

This mode could be controlled by the application or Scintilla platform layer code or a combination. It is really only helpful when the window is scaled fractionally and this may be determined by the platform layer. It may change as the window is moved between screens and will be an extra chore for the application to manage.

Its likely that the referenced patch will grow as more elements need to handle it. I think the visible line end mode is one that needs to change. The way seamOverDraw is passed around is ugly and may have unforeseen effects: this could cause different results when printing, for example.

Neil

Mitchell

unread,
Mar 4, 2026, 10:25:19 AMMar 4
to scintilla...@googlegroups.com
Hi Neil,
The curses (terminal) platform treats each pixel as a cell, so it is very sensitive to any rectangle size changes. I haven’t tested this patch, but I’d like to know if this “overdrawing” can be optional. Or maybe the overdraw parameters can be ignored by the platform? (It’s hard for me to understand the patch by reading it by itself.)

I’d appreciate any thoughts you might have on this.

Cheers,
Mitchell

Neil

unread,
Mar 4, 2026, 4:19:42 PMMar 4
to scintilla-interest
Mitchell:
I haven’t tested this patch, but I’d like to know if this “overdrawing” can be optional. Or maybe the overdraw parameters can be ignored by the platform? (It’s hard for me to understand the patch by reading it by itself.)

Yes, the overdraw will be optional and it may be up to the platform layer to enable it.

Perhaps overdraw is completely determined by the platform layer. Or there could be an API.

The decision could be a combination of the platform layer and an API.

There are other APIs like `SCI_SETTECHNOLOGY` and `SCI_SETBIDIRECTIONAL` where some platform layers intercept the call to restrict the possibilities such as refusing bidirectional mode.

Sometimes scaling information is available at an application level but is not easily available from a widget. On Win32, for example, some messages only go to topmost windows.

In the opposite direction, requiring applications to use an API means this will be less automatic which will lead to a poorer default experience.

The patch does not include an API or any platform enabling since its just trying to see if the idea is workable.

Neil 

John Ehresman

unread,
Mar 4, 2026, 11:40:46 PMMar 4
to scintilla...@googlegroups.com
Apologies for not looking into this sooner. I think Qt can render to the raw screen or device pixels (or at least the backing pixmap that Qt draws to before sending to the screen).

The way to simulate / adjust the scaling factor is to use the QT_SCALE_FACTOR environment variable; e.g QT_SCALE_FACTOR=1.5 testprogram

One way to draw to raw pixels is to render to a full size pixmap, set the device pixel ratio to match the widget, then render the pixmap to the widget.

It also may be possible to set the scale on a painter to 1 / device-pixel-ratio and then draw.

I may be able to try to fix this in scintilla, but it probably won’t be immediately.

John
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/5530760c-3b48-4610-8c57-0ec3fc6381den%40googlegroups.com.

Neil

unread,
Mar 6, 2026, 7:17:37 PMMar 6
to scintilla-interest
John:

One way to draw to raw pixels is to render to a full size pixmap, set the device pixel ratio to match the widget, then render the pixmap to the widget.

It also may be possible to set the scale on a painter to 1 / device-pixel-ratio and then draw.

These will be better approaches.

The earlier patch on this thread is improved a bit in case it is needed for other platforms.

This applies to the current repository state since a recent commit reduced draw calls for visible whitespace background by using a single call for a sequence of spaces instead on one call per space. Its faster and removes seams between spaces.

The Larger3.patch change moves the controlling variable to ViewState where it can be set differently for screen and printer. The decision is now made in the platform layer inside ScintillaQt.cpp. Seam overdraw is turned off for integer scaling 1x and 2x and also, to allow experimentation, for 1.5x.

Neil

Neil

unread,
May 22, 2026, 2:03:17 AMMay 22
to scintilla-interest
Implemented scaling for Qt with the attached patch. It works, like John suggested, drawing into a full size bitmap then copying that to the window.

An image showing both the new implementation (left) and the old (right) at 150% scaling can be seen at https://www.scintilla.org/QtScale.png .

Just setting the painter scale to 1/scalingFactor should have worked but still produces seams. It's possible that scaling is being performed twice here.

This does some extra work since the entire Scintilla window is redrawn for every change so can be slow although it is mostly adequate. There is some commented-out code in Window::InvalidateRectangle that tried to redraw just the rectangle needed but, while this almost worked, there were occasional single pixel line debris when selecting with the mouse. It is likely that scaling will need to be applied in more places.

The code builds and works with Qt 6.10.2 on both Linux (Ubuntu 26.04 Wayland) and Windows 10. It will likely need #if to avoid new APIs for projects still with Qt 5.x.

There is an updated version of Haven that can test this at https://www.scintilla.org/HavenScale.zip . It uses a dark background as that makes seams more prominent when the system is in standard light 'daytime' mode.

Since this will need Qt version checks and may decrease performance, it is likely this will be delivered behind a preprocessor switch so downstream projects can opt into the change.

Neil

QtScale5.patch

Mitchell

unread,
May 22, 2026, 2:18:40 PMMay 22
to scintilla...@googlegroups.com
Hi Neil,

> On May 22, 2026, at 2:03 AM, Neil <scintil...@gmail.com> wrote:
>
> Implemented scaling for Qt with the attached patch. It works, like John suggested, drawing into a full size bitmap then copying that to the window.
>
> An image showing both the new implementation (left) and the old (right) at 150% scaling can be seen at https://www.scintilla.org/QtScale.png .

[snip]

I applied this patch to Qt 6 on macOS and I’m seeing some really weird effects. I’m on a Retina display, so that’s probably messing with the devicePixelRatio() computations.

See attached noscale.png and yesscale.png images. The arrows in the latter point to the weird things I’m seeing:
- hard to see indicators
- hard to see margin symbols
- too large autocompletion window

I looked at the documentation to try and find an option to set scaling, but I couldn’t find it. I assume the patch is supposed to detect and apply scaling via the devicePixelRatio() computations.

Cheers,
Mitchell

noscale.png
yesscale.png

Neil

unread,
May 23, 2026, 1:23:17 AMMay 23
to scintilla-interest
Mitchell:
 
I applied this patch to Qt 6 on macOS and I’m seeing some really weird effects.

Thanks for looking at the change. Some of these can be fixed and others are from decisions made when implementing scaling for Win32 and may require application additions or new APIs.
 
I’m on a Retina display, so that’s probably messing with the devicePixelRatio() computations.

Yes, macOS scales differently which makes it easy for macOS apps but may cause problems when Qt treats scaling more like Windows.

On Windows, scale factors between 100% and 200% are common - I mostly use a 4K monitor with Windows and Windows recommends 150%.

At 200% (as is common on macOS), it is reasonable to double all dimensions, making simple lines 2 pixels wide. At 150%, some people will prefer 1 pixel wide lines and some 2. Using floating point widths such as a 1.5 pixel wide lines will lead to 'fuzzy' features that are widely disliked. So I left most features with their original pixel widths with the intent of making more choices available so that applications and users can choose something that works for them and they can choose when to switch between feature sizes.

See attached noscale.png and yesscale.png images. The arrows in the latter point to the weird things I’m seeing:
- hard to see indicators

Most indicators do not scale. IndicatorStyle::Diagonal, in particular, tries to fit 3 pixel high underlines in the text descender area which is quite tight so may result in clipping.

With 'noscale.png' macOS Retina scaling, 3 pixels = 6 physical pixels which looks quite good. 'yesscale.png' is using 3 physical pixels so looks too faint. A new indicator (which I think should have a new name) could be implemented in various ways. The descender height could determine the height and spacing of the diagonal lines although that will decrease density. The stroke width could be made wider although it should probably remain an integer - a 1.5 pixel wide line here produces an less distinct blob.
 
- hard to see margin symbols

The margins are specified in physical pixels so the application should (if desired) scale the argument to SCI_SETMARGINWIDTHN. The reason Scintilla doesn't automatically scale these is that symbol margins are particularly sensitive to tweaking and I wanted applications to control exactly how wide margins are. SciTE provides a '$(scale)' function that may be used until more control is wanted.
 
- too large autocompletion window

The scale factor was applied twice to the font size and the size and position of the window so there is an update with an inverse scale in ListBoxImpl::SetFont and Window::SetPositionRelative then a compensating scale in ListBoxImpl::GetDesiredRect.

This is just part of the division between scaled graphics coordinates used by this patch and the need to coordinate with the window layer. Scaling could be handled more thoroughly with the factor flowing through the data structures although this would be more intrusive. The implementation here is trying to get this working with a small change to the edge of Scintilla, just in the Qt platform layer.

A QtScale7.patch that includes these changes is attached.
 
I looked at the documentation to try and find an option to set scaling, but I couldn’t find it. I assume the patch is supposed to detect and apply scaling via the devicePixelRatio() computations.

Yes, this is trying to be automatic, at least for basic uses. There could be an API either to set a scaling factor or just to control whether the scaling is enabled.

Also experimented with Qt 5.15.10 and the only symbol missing was QEvent::DevicePixelRatioChange so there is an #if to avoid that before it is available. All the devicePixelRatioF calls appear to work on Qt 5 which is great. The DevicePixelRatioChange  event was intercepted as otherwise Haven started up with 200% instead of 150% scaling - it appears that the accurate scaling factor is only discovered after the window is shown.

There is a further problem with current Ubuntu+Wayland in that the windows for autocompletion and calltips fail as they do not have an owning window as their transientParent. Wayland doesn't like applications showing top-level windows at arbitrary locations and wants these to be attached to owning windows. This has been a minor problem in the past with GTK but it mostly led to windows located poorly rather than failing. The relevant API setTransientParent can't be called after the window creation as creation has already failed and there may need to be some set up during the right stage of window construction / realization. This is orthogonal to scaling so may be something that one of the users of Qt on Linux can investigate.

Neil
QtScale7.patch

Mitchell

unread,
May 23, 2026, 7:45:22 PMMay 23
to scintilla...@googlegroups.com
Hi Neil,

> [snip]
>
> See attached noscale.png and yesscale.png images. The arrows in the latter point to the weird things I’m seeing:
> - hard to see indicators
>
> Most indicators do not scale. IndicatorStyle::Diagonal, in particular, tries to fit 3 pixel high underlines in the text descender area which is quite tight so may result in clipping.
>
> With 'noscale.png' macOS Retina scaling, 3 pixels = 6 physical pixels which looks quite good. 'yesscale.png' is using 3 physical pixels so looks too faint. A new indicator (which I think should have a new name) could be implemented in various ways. The descender height could determine the height and spacing of the diagonal lines although that will decrease density. The stroke width could be made wider although it should probably remain an integer - a 1.5 pixel wide line here produces an less distinct blob.

I like the indicators that I see without the patch. Having multiple new scale-specific indicators doesn’t sound ideal.

> - hard to see margin symbols
>
> The margins are specified in physical pixels so the application should (if desired) scale the argument to SCI_SETMARGINWIDTHN. The reason Scintilla doesn't automatically scale these is that symbol margins are particularly sensitive to tweaking and I wanted applications to control exactly how wide margins are. SciTE provides a '$(scale)' function that may be used until more control is wanted.

I increased my margin width using your new patch, but the markers remained the same, small size. Do I need to implement some sort of client-side scaling?

> - too large autocompletion window
>
> [snip]
>
> A QtScale7.patch that includes these changes is attached.

I confirm this is fixed.

I did run into a strange issue with a Scintilla view that is normally 1 line high is now 2 lines high. However, I set the height using the SCI_TEXTHEIGHT, so I suspect Scintilla is reporting a new scaled height. Either I have to divide by two, or Scintilla (or its Qt platform) needs to do another computation somewhere.

> I looked at the documentation to try and find an option to set scaling, but I couldn’t find it. I assume the patch is supposed to detect and apply scaling via the devicePixelRatio() computations.
>
> Yes, this is trying to be automatic, at least for basic uses. There could be an API either to set a scaling factor or just to control whether the scaling is enabled.

I would like some sort of control to disable scaling and keep the default drawing Scintilla Qt is doing on my Retina and 4K display (I assume macOS is doing 200% scaling for both). When I have time, I can enable scaling and then identify and report any issues I find, as I am now. Right now it feels like I’m going to run into a lot of small things over time rather than all at once. I’d be more comfortable with the fallback to disable and keep the current drawing.

Cheers,
Mitchell

Neil

unread,
May 24, 2026, 11:34:49 PMMay 24
to scintilla-interest
There were some more problems on current Wayland with the popups reporting a devicePixelRatioF of 2.0 when the system scale was 1.5 or 1.33. Its possible this is an initialization issue with windows not knowing an accurate scaling factor before they receive a set scale message. It was fixed by using the devicePixelRatioF of the main Scintilla window in the attached patch.

Mitchell:

I like the indicators that I see without the patch. Having multiple new scale-specific indicators doesn’t sound ideal.

It's more likely you will be able to replace Diagonal with a single new DiagonalProportionalToDescender (or similar name) that implements a particular style of scaling diagonals. If there are different opinions on the best technique to use then there could be more than one Diagonal*. A constraint here is that downstream Windows projects have been scaling for 6 years and shouldn't have their appearance modified in ways that they may not like or want.

I increased my margin width using your new patch, but the markers remained the same, small size. Do I need to implement some sort of client-side scaling?

It is likely you will have to perform some scaling yourself.

I did run into a strange issue with a Scintilla view that is normally 1 line high is now 2 lines high. However, I set the height using the SCI_TEXTHEIGHT, so I suspect Scintilla is reporting a new scaled height. Either I have to divide by two, or Scintilla (or its Qt platform) needs to do another computation somewhere.

I'm not sure. There are really two scales working in the code: graphics and windowing with window coordinates not being scaled.

I would like some sort of control to disable scaling and keep the default drawing Scintilla Qt is doing on my Retina and 4K display (I assume macOS is doing 200% scaling for both). When I have time, I can enable scaling and then identify and report any issues I find, as I am now. Right now it feels like I’m going to run into a lot of small things over time rather than all at once. I’d be more comfortable with the fallback to disable and keep the current drawing.

I have been working on this but scaling occurs in many places and the 'scaled' control property needs to be distributed and kept current.

Neil
QtScaleA.patch

Mitchell

unread,
May 25, 2026, 11:32:41 AMMay 25
to scintilla...@googlegroups.com
Hi Neil,

> On May 24, 2026, at 11:34 PM, Neil <scintil...@gmail.com> wrote:
>
> There were some more problems on current Wayland with the popups reporting a devicePixelRatioF of 2.0 when the system scale was 1.5 or 1.33. Its possible this is an initialization issue with windows not knowing an accurate scaling factor before they receive a set scale message. It was fixed by using the devicePixelRatioF of the main Scintilla window in the attached patch.
>
> Mitchell:
>
> I like the indicators that I see without the patch. Having multiple new scale-specific indicators doesn’t sound ideal.
>
> It's more likely you will be able to replace Diagonal with a single new DiagonalProportionalToDescender (or similar name) that implements a particular style of scaling diagonals. If there are different opinions on the best technique to use then there could be more than one Diagonal*.

That’s precisely what I’m concerned about. I use diagonal and squiggly indicators. They would each need their own scaled versions, possibly with more permutations. My application would have to pick an indicator based on detected scaling, etc. Right now, Qt already draws things correctly, even in my HiDPI Ubuntu 24.04 VM with 200% scaling.

> A constraint here is that downstream Windows projects have been scaling for 6 years and shouldn't have their appearance modified in ways that they may not like or want.

I think I could say my Mac project has been scaling for 6 years :) Or maybe I misunderstand your meaning.

> I increased my margin width using your new patch, but the markers remained the same, small size. Do I need to implement some sort of client-side scaling?
>
> It is likely you will have to perform some scaling yourself.

Okay, so another client-side branch based on whether or not the application is running on a HiDPI display.

> I did run into a strange issue with a Scintilla view that is normally 1 line high is now 2 lines high. However, I set the height using the SCI_TEXTHEIGHT, so I suspect Scintilla is reporting a new scaled height. Either I have to divide by two, or Scintilla (or its Qt platform) needs to do another computation somewhere.
>
> I'm not sure. There are really two scales working in the code: graphics and windowing with window coordinates not being scaled.

That’s what I was afraid of. Now I need to become an expert to know the difference between what units Scintilla’s APIs are reporting, and what units the Window toolkit is reporting.

> I would like some sort of control to disable scaling and keep the default drawing Scintilla Qt is doing on my Retina and 4K display (I assume macOS is doing 200% scaling for both). When I have time, I can enable scaling and then identify and report any issues I find, as I am now. Right now it feels like I’m going to run into a lot of small things over time rather than all at once. I’d be more comfortable with the fallback to disable and keep the current drawing.
>
> I have been working on this but scaling occurs in many places and the 'scaled' control property needs to be distributed and kept current.

I understand. It’s a hard issue with a non-zero maintenance burden.

Ultimately I will accept and adjust to whatever changes you make. I’m just offering my feedback now at this early stage for what it’s worth.

Cheers,
Mitchell

John Ehresman

unread,
May 25, 2026, 12:52:21 PMMay 25
to scintilla...@googlegroups.com
I’ve begun looking at this, though only with Haven so far. Haven does show the issues with margin width / stroke width — I mention it because I thought the INDIC_CONTAINER under the first two letters was a bug because it renders as a one device pixel black line that looks like a seam with the patched version of scintilla.

I plan to do more testing in the next few days.

Thanks,

John
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/96031856-CB8D-45BE-9B32-3ADC515E511B%40foicica.com.

Neil Hodgson

unread,
May 28, 2026, 4:13:27 AMMay 28
to scintilla...@googlegroups.com
Mitchell:

> That’s precisely what I’m concerned about. I use diagonal and squiggly indicators. They would each need their own scaled versions,
> possibly with more permutations. My application would have to pick an indicator based on detected scaling, etc.

It's likely not possible to enable good fractional scaling without
some modifications to applications.

> Right now, Qt already draws things correctly, even in my HiDPI Ubuntu 24.04 VM with 200% scaling.

If only integral scaling was desired then there could be a simpler
implementation similar to macOS but that would be less capable than
Win32.

Neil

Neil Hodgson

unread,
May 28, 2026, 7:28:26 AMMay 28
to scintilla...@googlegroups.com
Attached is a patch that adds a ScintillaEditBase::SetScaled(bool
scaled) API that allows turning scaled mode on.

This change was difficult to make work so is probably fragile, not
minimal and may add new problems.

For Haven, I've been testing with placing the control in the "Wrap"
toggle menu item.

void MainWindow::on_actionWrap_triggered() {
Call(SCI_SETWRAPMODE, Call(SCI_GETWRAPMODE) ? SC_WRAP_NONE : SC_WRAP_WORD);
ui->blok->SetScaled(!ui->blok->Scaled());
}

Neil
QtScaleE.patch

Mitchell

unread,
May 29, 2026, 12:04:36 PMMay 29
to scintilla...@googlegroups.com
Hi Neil,
I have no idea why, but I’m getting scaled behavior by default on macOS, even if I manually call `SetScaled(false)` (which I shouldn’t have to, because it’s false by default).

```
auto view = new ScintillaEditBase;
view->SetScaled(false);
```

I reversed the patch, rebuilt, and I’m not seeing any more scaled behavior, so the patch is doing something, just not the expected thing.

Cheers,
Mitchell

Neil Hodgson

unread,
May 29, 2026, 9:44:14 PMMay 29
to scintilla...@googlegroups.com
Mitchell:

> I have no idea why, but I’m getting scaled behavior by default on macOS, even if I manually call `SetScaled(false)` (which I shouldn’t have to, because it’s false by default).

Yes, some of the effects are unexpected. Where above I said "difficult
to make work", part of that was that some changes made to disable
scaling were ineffective so scaling was reinstated. It's possible that
a Qt (or platform) internal scaling mode is set unexpectedly by
something like calling devicePixelRatioF.

A new issue I have noticed on Windows is that changing the system
scaling can cause the scroll bar to move a little sideways until the
window is resized. This may require a work-around like the application
resizing its widgets explicitly.

An updated Haven with a separate Scale menu item, margins that resize
on scale change event, and better dark-mode settings is available from
https://www.scintilla.org/HavenScale2.zip

Neil

Neil Hodgson

unread,
Jun 10, 2026, 9:30:36 PMJun 10
to scintilla...@googlegroups.com
Some new changes should make non-scaled mode more like previous
versions although there are some regressions as well.

Widgets that may be scaled are now tagged with a "ScintillaScale"
property which is either the devicePixelRatioF to apply or 0.0 if
scaling is turned off. This allows scaling code dispersed in multiple
locations (like the Surface implementation) to more easily find the
correct factor to apply.

The line height may differ from the previous version. Scaled mode
chooses an integer line height (in screen space) whereas non-scaled
mode uses a fractional value so there will be change in layout between
modes but this change may be truncating instead of rounding or
similar.

The area invalidation code no longer updates the whole window in more
cases such as when the scale is an integer or its executing on Win32.
There may need to be more tweaks here, particularly for macOS which I
haven't checked.

There are problems with text size of calltips in unscaled mode on
Wayland with a fractional scale where it seems to use trunc(scale).

The problem with the vertical scroll bar not staying aligned to the
edge when the system scale is reduced on Win32 is still not fixed.
This may be a re-entrance issue in handling scale change notifications
and may require a deferred fixup task.

Calling the new mode "scaled" may be too loose as the previous
implementation did perform scaling. Perhaps a name based on "pixel
snapping" or "seam avoidance" may be better.

https://www.scintilla.org/QtScaleF.patch
https://www.scintilla.org/HavenScale3.zip

Neil

Mitchell

unread,
Jun 11, 2026, 9:50:33 AMJun 11
to scintilla...@googlegroups.com
Hi Neil,

> On Jun 10, 2026, at 9:30 PM, Neil Hodgson <scintil...@gmail.com> wrote:
>
> Some new changes should make non-scaled mode more like previous
> versions although there are some regressions as well.

I can confirm on macOS at least that scaling is off by default after applying the patch. Calling `SetScaled(true)` turns it on.

I have not looked for regressions though. Things look okay at first glance.

Cheers,
Mitchell

Neil Hodgson

unread,
Jun 11, 2026, 7:07:12 PMJun 11
to scintilla...@googlegroups.com
Mitchell:

> I can confirm on macOS at least that scaling is off by default after applying the patch. Calling `SetScaled(true)` turns it on.

Yeah, that's the main thing for this version. The 'scaled' status
should be accurate and distributed over the code promptly with fewer
chances of stale effects.

> I have not looked for regressions though. Things look okay at first glance.

Non-scaled mode may not set the vertical scroll bar correctly making
the end of file unreachable. I think this is likely a float truncation
or similar issue.

There are more differences between platforms than I was initially
expecting. This may be due to message sequencing or reentrance locks.

Neil

Neil Hodgson

unread,
Jun 15, 2026, 7:56:23 PM (12 days ago) Jun 15
to scintilla...@googlegroups.com
An updated version is available that fixes problems with scrolling and
position+size of calltips and autocompletion.

A ScaleTechnique property was added with values
SCALE_TECHNIQUE_DEFAULT=0, SCALE_TECHNIQUE_PIXEL_ALIGNED=1 controlled
with a SCI_SETSCALETECHNIQUE API.

The ScaleTechnique property may get additional enumeration values or
modifying bit flags with future refinements. This feature is marked
provisional so may change.

While the calltips and autocompletion lists are positioned under the
caret, they do not always flip above the caret when there is no room
below. This is because scaling is not consistently taken into account
when checking the bottom of the screen or window.

Autocompletion lists were made slightly wider as text could be
truncated with ... in some cases. This is from converting coordinates
that are scaled by a fraction to integers and there may be other
instances with similar issues.

The patch changes the location of the output shared libraries to be in
scintilla/bin as they were often in
scintilla/qt/ScintillaEditBase/bin. Newer versions of qmake (or Qt
Creator) seemed to use a different base or current directory when
building and this caused problems for downstream projects like Haven
that were coded to previous behaviour.

Haven was updated as https://www.scintilla.org/HavenScale4.zip to
match the changes in the patch.

Patch attached.

This may be committed to the main repository for the next release, so
anyone who thinks it may cause problems or want changes should speak
up now.

Neil
QtScaleH.patch

Mitchell

unread,
Jun 15, 2026, 10:20:09 PM (12 days ago) Jun 15
to scintilla...@googlegroups.com
Hi Neil,

> On Jun 15, 2026, at 7:56 PM, Neil Hodgson <scintil...@gmail.com> wrote:
>
> An updated version is available that fixes problems with scrolling and
> position+size of calltips and autocompletion.
>
> A ScaleTechnique property was added with values
> SCALE_TECHNIQUE_DEFAULT=0, SCALE_TECHNIQUE_PIXEL_ALIGNED=1 controlled
> with a SCI_SETSCALETECHNIQUE API.

I like this! Thank you for adding it.

I found a bug though: on macOS when I use the API to change to PIXEL_ALIGNED scaling, all drawing shrinks by half (text is tiny). I have to increment and decrement zoom level to make drawing fine again. Similarly, when I use the API to go back to DEFAULT, all drawing multiplies by two (text is huge). When I decrement and increment zoom level, drawing is fine again.

I imagine you are already aware, but just in case, some markers need to adjust their drawing to accommodate the new scale tech. For example, I am using box tree fold margin markers. When I double my margin size from 12 to 24 with PIXEL_ALIGNED, I am getting the expected size, but the inner “-“ and “+” symbols pretty much touch the boxes when they should be inset more (probably double).

I will continue to play with this, but so far so good.

Cheers,
Mitchell

>
> The ScaleTechnique property may get additional enumeration values or
> modifying bit flags with future refinements. This feature is marked
> provisional so may change.
>
> While the calltips and autocompletion lists are positioned under the
> caret, they do not always flip above the caret when there is no room
> below. This is because scaling is not consistently taken into account
> when checking the bottom of the screen or window.
>
> Autocompletion lists were made slightly wider as text could be
> truncated with ... in some cases. This is from converting coordinates
> that are scaled by a fraction to integers and there may be other
> instances with similar issues.
>
> The patch changes the location of the output shared libraries to be in
> scintilla/bin as they were often in
> scintilla/qt/ScintillaEditBase/bin. Newer versions of qmake (or Qt
> Creator) seemed to use a different base or current directory when
> building and this caused problems for downstream projects like Haven
> that were coded to previous behaviour.
>
> Haven was updated as https://www.scintilla.org/HavenScale4.zip to
> match the changes in the patch.
>
> Patch attached.
>
> This may be committed to the main repository for the next release, so
> anyone who thinks it may cause problems or want changes should speak
> up now.
>
> Neil
>
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/CACWkrTgsnwcr_8C53NfpBfFptT%2B5dURNTE3vHWJpG2i6MumVhQ%40mail.gmail.com.
> <QtScaleH.patch>

Mitchell

unread,
Jun 15, 2026, 10:23:09 PM (12 days ago) Jun 15
to scintilla...@googlegroups.com
Hi,

> On Jun 15, 2026, at 10:19 PM, Mitchell <co...@foicica.com> wrote:
>
> I found a bug though: on macOS when I use the API to change to PIXEL_ALIGNED scaling, all drawing shrinks by half (text is tiny). I have to increment and decrement zoom level to make drawing fine again. Similarly, when I use the API to go back to DEFAULT, all drawing multiplies by two (text is huge). When I decrement and increment zoom level, drawing is fine again.

To clarify: a single increment will make drawing almost right (one point too big), and a single decrement will make drawing right (net zero zoom).

Mitchell

Neil Hodgson

unread,
Jun 16, 2026, 7:54:18 AM (12 days ago) Jun 16
to Scintilla mailing list
Mitchell:

> I found a bug though: on macOS when I use the API to change to PIXEL_ALIGNED scaling, all drawing shrinks by half (text is tiny).

> To clarify: a single increment will make drawing almost right (one point too big), and a single decrement will make drawing right (net zero zoom).


That makes it sound like a sequencing problem similar to earlier code on Linux+Wayland where an incorrect initial scale was fixed subsequently. For the Linux case, it was only necessary to choose a different encoding value as that forced through a view reset. This was fixed by handling the QEvent::DevicePixelRatioChange event but I'm not getting that to occur on macOS.

OK, I have now seen something similar once when in the debugger which may have upset event handling. Perhaps the SetScaleProperty method needs to be called when handling Message::SetScaleTechnique inside ScintillaQt::WndProc although SetScaleProperty is called at the start of each paint.

> I imagine you are already aware, but just in case, some markers need to adjust their drawing to accommodate the new scale tech. For example, I am using box tree fold margin markers. When I double my margin size from 12 to 24 with PIXEL_ALIGNED, I am getting the expected size, but the inner “-“ and “+” symbols pretty much touch the boxes when they should be inset more (probably double).

I don't mind it myself but I can see that others wouldn't. Maybe change the insetting of the symbol box with a factor based on a proportion of the box size but with a minimum of the current value. The code is in LineMarker.cxx inside DrawSymbol.

Neil

John Ehresman

unread,
Jun 16, 2026, 8:04:56 AM (12 days ago) Jun 16
to scintilla...@googlegroups.com
I was working with your prior patch yesterday and have updated to the new patch. I have two patches and the first modifies the Qt widget method generation to add *F() variants of methods that take or return pixel values — these mimic how Qt works by always working in (possibly fractional) pixel units. Our code uses scintilla through these methods; we’re beginning to migrate to using the float variants; the integer methods work with the expected limitations.

The second patch uses full repaints on macOS because I intermittently see a one pixel of selection color when I select and deselect lines (though I can trigger it pretty easily). I’ve only tested on macOS so far so this may be a problem on win32 as well; I’m using a QT_SCALE_FACTOR=8.5 to test. The patch also fixes the initial tiny text problem and a scroll by lines bug.

I’m going to see if I can figure out where the one pixel line comes from.

Thanks,

John

QtScale-pixels-method-gen.patch
QtScale-platform-fixes.patch

Neil Hodgson

unread,
Jun 16, 2026, 11:38:50 PM (11 days ago) Jun 16
to scintilla...@googlegroups.com
John Ehresman:

> to add *F() variants of methods that take or return pixel values — these mimic how Qt works by always working in (possibly fractional) pixel units.

Tagging APIs that take or return pixels is good.

Scripts that read Scintilla.iface will need to be updated to
understand 'pixels'. Some of these are in Scintilla
(ScintillaAPIFacer.py, CheckMentioned.py) and SciTE (IFaceTableGen.py)
but some are in external projects.

Since this could cause failures in these projects, I'd like to provide
some transition support. Perhaps by publishing a script that converts
'int' into 'pixels' in Scintilla.iface where appropriate so projects
could update on their own schedule then force the update in a release
or two.

There will be decisions on how to expose this: does ScintillaTypes.h
get a 'using Pixels = intptr_t;' with ScintillaCall.h then specifying
'Pixels' in methods? Is the documentation updated or left with 'int'?

> The second patch uses full repaints on macOS because I intermittently see a one pixel of selection color when I select and deselect lines (though I can trigger it pretty easily).

Yes, I have seen this too and do not understand it. It would be more
understandable if it happened on line edges where a float to int
rounding could cause a gap in painting but the selection remnant can
appear well inside a line. If it was just an edge truncation then
expanding the rectangle a little up and down would fix it but that
doesn't work.

For PixelAligned scaling, there is a performance cost to redrawing the
whole screen range, so accurate invalidation could be followed by
restricting painting to just the necessary area in the future.

> The patch also fixes the initial tiny text problem and a scroll by lines bug.

They look good.

I have applied QtScale-platform-fixes.patch and attached is a combined patch.

Neil
QtScaleI.patch

John Ehresman

unread,
Jun 17, 2026, 3:31:05 PM (10 days ago) Jun 17
to scintilla...@googlegroups.com
> On Jun 17, 2026, at 4:38 AM, Neil Hodgson <scintil...@gmail.com> wrote:
>> to add *F() variants of methods that take or return pixel values — these mimic how Qt works by always working in (possibly fractional) pixel units.
> ...
> Since this could cause failures in these projects, I'd like to provide
> some transition support. Perhaps by publishing a script that converts
> 'int' into 'pixels' in Scintilla.iface where appropriate so projects
> could update on their own schedule then force the update in a release
> or two.

The list could be in WidgetGen.py for now until .iface is updated or put temporary comments in the .iface file.

> There will be decisions on how to expose this: does ScintillaTypes.h
> get a 'using Pixels = intptr_t;' with ScintillaCall.h then specifying
> 'Pixels' in methods? Is the documentation updated or left with 'int'?

Making it a C++ alias might be good — but I rarely work with C++ these days so I’m not the one to ask.

>> The second patch uses full repaints on macOS because I intermittently see a one pixel of selection color when I select and deselect lines (though I can trigger it pretty easily).
>
> Yes, I have seen this too and do not understand it.

It’s apparently a bug with the Qt backing store on macOS. There are 2+ backing stores and when a paint with a clip is done, the portions outside the clip can be copied from another backing store and the portions in the clip drawn by the widget. The problem seems to be that the copy from another backing store is done with logical pixel rects that are rounded to device pixels and the clip is applied in device pixels — which can lead to 1+ device pixel lines that aren’t filled by either so they retain whatever values they had originally. What seems to work is enlarging the invalidated rect so it has coordinates that are multiples of device / logical pixels — if there are 3 device pixels per logical pixels, the coordinates need to be multiples of 3 so there aren’t any rounding gaps.

Attached is a patch that seems to work — note that on some ratios, it will revert to a full redraw. I have only tried this on macOS but plan to try it on the other platforms soon.

John

QtScale-PlatQt.patch

Neil Hodgson

unread,
Jun 17, 2026, 8:43:28 PM (10 days ago) Jun 17
to Scintilla mailing list
John:

> Attached is a patch that seems to work — note that on some ratios, it will revert to a full redraw. I have only tried this on macOS but plan to try it on the other platforms soon.

This does appear to help when scale is turned on.

However, it may also be needed for ScaleTechnique::Default. Here is an image when QT_SCALE_FACTOR=1.5.
https://www.scintilla.org/MacOS-Seam-150.jpg

Neil

Neil Hodgson

unread,
Jun 18, 2026, 6:35:23 PM (9 days ago) Jun 18
to scintilla...@googlegroups.com
Me:

> However, it may also be needed for ScaleTechnique::Default. Here is an image when QT_SCALE_FACTOR=1.5.

While fractional scaling is worthwhile and common on other platforms
and coding for fractional scaling is good generality, it probably
doesn't matter on macOS. On macOS, the operating system does whole
screen stretching for fractional scales with applications seeing an
integer scale.

It would be unusual (but possible) for a user to set the
QT_SCALE_FACTOR environment variable before running an app - I'd
personally consider it for using Qt Creator as a debugger since the
many panes are often cluttered so hide the data I'm trying to track.

Perhaps some applications want to control QT_SCALE_FACTOR with a user
preference mechanism.

Neil

Neil Hodgson

unread,
Jun 18, 2026, 6:46:56 PM (9 days ago) Jun 18
to scintilla...@googlegroups.com
The lines of markers and indicators can be made thicker with the
SCI_MARKERSETSTROKEWIDTH and SCI_INDICSETSTROKEWIDTH APIs, This is not
automatic so requires application code.

Changing Haven's MainWindow::rescale code like the following switches
between single pixel and double pixel lines at 170%. The points at
which different thicknesses are applied is up to the application
designer. It looks like
https://www.scintilla.org/QtScaleStrokeWidth.png at 175% on Windows.

void MainWindow::rescale() {
const qreal scale = isScaled() ? devicePixelRatioF() : 1.0;
Call(SCI_SETMARGINWIDTHN, 0, lround(scale * 40));
Call(SCI_SETMARGINWIDTHN, 1, lround(scale * 16));
Call(SCI_SETMARGINWIDTHN, 2, lround(scale * 13));

const int strokeWidth = scale > 1.7 ? 200 : 100;
for (int mark = SC_MARKNUM_FOLDEREND; mark <=
SC_MARKNUM_FOLDEROPEN; mark++) {
Call(SCI_MARKERSETSTROKEWIDTH, mark, strokeWidth);
}

Call(SCI_INDICSETSTROKEWIDTH, INDIC_CONTAINER, strokeWidth);
}


Neil

Mitchell

unread,
Jun 18, 2026, 7:58:48 PM (9 days ago) Jun 18
to scintilla...@googlegroups.com
Hi Neil,

> On Jun 18, 2026, at 6:46 PM, Neil Hodgson <scintil...@gmail.com> wrote:
>
> The lines of markers and indicators can be made thicker with the
> SCI_MARKERSETSTROKEWIDTH and SCI_INDICSETSTROKEWIDTH APIs, This is not
> automatic so requires application code.
>
> [snip]

Very cool. The boxed fold markers look better. My squiggle and hash indicators are also more visible, but still scrunched together since their draw routines do not take into account scaling. Still, it’s an improvement overall. Thanks for pointing out the stroke width APIs.

Cheers,
Mitchell

John Ehresman

unread,
Jun 19, 2026, 6:09:12 AM (9 days ago) Jun 19
to scintilla...@googlegroups.com
Here’s a version that always snaps. Haven’t tried it with default scaling technique but should work. Also added a define to disable it — I do have the start of a patch to Qt that seems to work for scintilla and for other widgets. The backing store has a grid of what is dirty and that grid is only half the size of the backing store on retina displays. Making it full size seems to fix the one pixel lines.

[I wrote this before seeing Neil’s followup message. I agree that scaling on macOS is less important (other than the default 2x), but it’s nice to know that the bug is not in scintilla and it actually works well when fixed]

John

QtScale-PlatQt.patch

Neil Hodgson

unread,
Jun 20, 2026, 7:21:19 PM (7 days ago) Jun 20
to scintilla...@googlegroups.com
John:

> Here’s a version that always snaps.

That worked for me on macOS.

> The backing store has a grid of what is dirty and that grid is only half the size of the backing store on retina displays. Making it full size seems to fix the one pixel lines.

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

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 == 1)` checks since there is no 'retina'
pixel-doubling
* Remove the early return for scales other than 1.0 and 2.0 in
InvalidateRectangle

This produces the expected 'q' of 2 (150%), 3 (133%), and 4 (125%) and
the corresponding snapped rectangle value.

Neil
EnableSnap.patch

John Ehresman

unread,
Jun 22, 2026, 7:18:57 AM (6 days ago) Jun 22
to scintilla...@googlegroups.com
Neil,

Wayland has a similar dirty region bug and I have a local patch to fix it. It’s a Qt bug — I see more debris lines in the list widget and menus more than I do in scintilla. But the snap workaround doesn’t seem to fix it and I’m trying to figure out why.

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 magnification are you using?

Thanks,

John
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/CACWkrTiX45E9qpTcUezPOyDHwDOi8oCbCirY0JnAAFwSkY5faA%40mail.gmail.com.
> <EnableSnap.patch>

John Ehresman

unread,
Jun 22, 2026, 4:19:59 PM (5 days ago) Jun 22
to scintilla...@googlegroups.com
The problem was that the upper left of the widget needs to be taken into account when snapping the rectangle. Here’s 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 — the issue is that Qt doesn’t expose it in its api that I know of and the Wayland’s magnification factor isn’t fixed at 2 like the factor for macOS retina displays.

I’ve only tested lightly on Wayland.

John

QtScale-PlatQt2.patch

Neil Hodgson

unread,
Jun 22, 2026, 9:33:53 PM (5 days ago) Jun 22
to scintilla...@googlegroups.com
John:

> I see the debris on Wayland when ... . What display magnification are you using?

I am using a display magnification of 150% set in the Gnome Settings
app; Displays page; Scale item. I am not setting QT_SCALE_FACTOR.

> Here’s 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 ...

That just returns a null QRect for me since I don't have
QT_SCALE_FACTOR set and Qt doesn't synthesize it. I stepped the code
in the debugger to where sf.isEmpty() so SnapToNativeWindowPixelGrid
returns early and the whole widget is repainted.

Changing the patch so that guiFactor defaults to the scaling factor
with `double guiFactor = winDpr;` produces no debris in some testing.

Neil

John Ehresman

unread,
Jun 23, 2026, 10:24:57 AM (5 days ago) Jun 23
to scintilla...@googlegroups.com
Neil,

I’ve been unable to reproduce, possibly because my Wayland setup is different than yours. I’m using a Ubuntu 24.04 based system and when the system display magnification is set to 150%, Wayland uses a 2.0 device pixel ratio and then scales the 200% to 150%.

My take now is that Qt scaling is buggy on macOS and Wayland — the listbox and menus show more debris than scintilla does when the highlighted item moves. The reason to maybe pursue this is that I don’t think there’s a problem if the qt scale factor is 1; if there is, then my Qt fix might be wrong / incomplete.

John
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/CACWkrTgXFz_GJEP8O7RaRDnn22dUUfU6z2YrD46Zt6yWpUGbgA%40mail.gmail.com.

Neil Hodgson

unread,
Jun 23, 2026, 6:28:30 PM (4 days ago) Jun 23
to scintilla...@googlegroups.com
John:

> I’ve been unable to reproduce, possibly because my Wayland setup is different than yours.

Yes, it could be system, library, or font matching issues. It could
also be occurring or not because of minor differences: lucking into an
evenly divisible line height or having the top of Scintilla at
different scale phases.

> I’m using a Ubuntu 24.04 based system and when the system display magnification is set to 150%, Wayland uses a 2.0 device pixel ratio and then scales the 200% to 150%.

OK, that is probably what is occurring to me since there is an initial
integer devicePixelRatioF then the DevicePixelRatioChange event
arrives and it updates to 1.5.

> My take now is that Qt scaling is buggy on macOS and Wayland — the listbox and menus show more debris than scintilla does when the highlighted item moves.

So, should I commit a version (attached) that leaves Wayland with
full-window invalidation for non-integer scaling? That would make it
easier for people to experiment with this since the bulk of the code
is more easily downloaded.

Patch includes your SCINTILLA_QT_BACKINGSTORE_FIXED change for macOS.

Neil
QtScaleK.patch

John Ehresman

unread,
Jun 24, 2026, 4:05:43 PM (3 days ago) Jun 24
to scintilla...@googlegroups.com
Neil:

I think it makes sense to commit this and then I’ll send you patches in the next few days to go on top of this. One change to maybe make now is to ifdef out the full repaint for Wayland if SCINTILLA_QT_BACKINGSTORE_FIXED is defined.

Thanks,

John
> --
> 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 email to scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/CACWkrTjzHj5q%3DxbTxtu2X7O0xb%3D03oqpCXubsb0%2Bt6Z8rXJugg%40mail.gmail.com.
> <QtScaleK.patch>

Neil Hodgson

unread,
Jun 24, 2026, 8:30:58 PM (3 days ago) Jun 24
to scintilla...@googlegroups.com
John:

> I think it makes sense to commit this and then I’ll send you patches in the next few days to go on top of this.
> One change to maybe make now is to ifdef out the full repaint for Wayland if SCINTILLA_QT_BACKINGSTORE_FIXED is defined.

OK. Committed.

Some other minor changes made:
Replaced deprecated Q_OS_OSX with Q_OS_MACOS to fix warning.
Moved output shared library to always be in scintilla/bin.
Reformatted 'else'.

The committed changes can be examined either in the repository

hg clone http://hg.code.sf.net/p/scintilla/code scintilla

or from

https://www.scintilla.org/scite.zip Source

Neil

John Ehresman

unread,
Jun 26, 2026, 6:05:44 AM (2 days ago) Jun 26
to scintilla...@googlegroups.com
Neil,

It seems to be working for me on Wayland. I’m attaching my 2nd try at a patch to add a pixels type to the .iface file — the pixels definitions are now in comments beneath the original definitions and there’s support in Face.py to read them. This should let other tools that use the .iface file and scripts to continue to work until they are updated.

Thanks,

John

pixel-iface-decls.diff

Neil Hodgson

unread,
Jun 26, 2026, 8:41:47 PM (2 days ago) Jun 26
to scintilla...@googlegroups.com
John:

> It seems to be working for me on Wayland. I’m attaching my 2nd try at a patch to add a pixels type to the .iface file — the pixels definitions are now in comments beneath the original definitions and there’s support in Face.py to read them. This should let other tools that use the .iface file and scripts to continue to work until they are updated.

OK.

The two features with fractional stroke widths MarkerSetStrokeWidth
and IndicSetStrokeWidth are hundredths so are actually pixels*100.
This allowed sending 0.5 widths (thin lines for macOS retina) over an
integer interface as 50.
These values may be scaled similarly to whole pixel features but are
fixed-point so may need different treatment.

Attached is a script that processes the Scintilla.iface augmented with
'pixels' into pre-pixels and post-pixels versions called
filtered.iface and pixels.iface. This can help if old code can't
handle the augmented version and to update to handle the final form
which will be distributed after the migration is complete.
Some projects use very simple iface-handling with tools like awk.

Neil
FilterPixels.py
Reply all
Reply to author
Forward
0 new messages