KRect and KRectF proposal

Vlad Zahorodnii vlad.zahorodnii at kde.org
Fri Mar 27 18:03:01 GMT 2026


Hi,

After hitting a number of issues with `QRect` and `QRectF` in KWin, we 
started a work on new rect helper counterparts that have fewer 
unexpected pitfalls. There are a number of issues with `QRect` and 
`QRectF`, for example some of them:

* `QRect::right()` and `QRect::bottom()` are off by one. One could argue 
that it's a well-known thing. But it's easy to miss it during a code 
review (maybe the author actually intended to have bottom() or right() 
off by 1, or maybe they were unaware that those edges are off by 1). It 
also leads to indirect side-effects, for example center() can return a 
value that makes no sense with an empty `QRect`;
* `QRectF::toRect()` has a smart rounding policy that is unsuitable for 
HiDPI on Wayland. People tend to use `toRect()` thinking that it does 
the right thing, but unfortunately, it just cannot be used if you want 
to render something properly with HiDPI;
* There are just some API bugs in `QRect`, e.g. the assert in 
`rect.moveCenter(center); Q_ASSERT(rect.center() == center);` can trip. 
(Just in case, we attempted to fix it upstream, but it turned out to be 
more challenging than expected so it got stuck);
* etc

The rect helpers in kwin address a bunch of issues that we had 
encountered with `QRect` and `QRectF`. However, they also go slightly 
further and add some new useful APIs. Some key things about the new rect 
types:

- `Rect::right()` and `Rect::bottom()` represent the true right and 
bottom edges, respectively. In other words, `x() + width()` and `y() + 
height()`;
- `RectF::contains()` does not consider the right and bottom edges 
inside the rectangle. Current `QRectF::contains()` can lead to issues 
with input handling;
- `RectF::toRect()` rounds the coordinates of top, left, right, and 
bottom edges;
- `RectF::rounded()`, `RectF::roundedIn()`, `RectF::roundedOut()` for 
various rounding strategies. `rounded()` can be used for general 
geometry, `roundedOut()` for repaints, `roundedIn()` for things like the 
opaque region, etc;
- Less confusing names for growing and shrinking rects, i.e. 
`Rect::grownBy()` and `Rect::shrunkBy()`;
- `Rect::horizontalCenter()` and `Rect::verticalCenter()` + 
`Rect::moveHorizontalCenter()` and `Rect::moveVerticalCenter()`, 
respectively;
- `Rect::scaled()` and `RectF::scaled()` for scaling rectangles. It is 
pretty common when working with HiDPI.

We had interoperability between `QRect`/`QRectF` and `KRect`/`KRectF` 
back in our mind. The idea is that you should be able to swap out 
`QRect`/`QRectF` for `KRect`/`KRectF` in your code with minimal changes. 
You don't have to rewrite the project to use `KRect` or `KRectF`, you 
should be able to combine them with existing code that uses `QRect` + 
`QRectF` and gradually migrate to the new types.

Our long term hope is that Qt developers would see what KDE does with 
`KRect` and `KRectF` and consider either fixing `QRect` and `QRectF` or 
incorporating them as is to Qt. Right now, if we go with our list of 
issues, we will likely be turned around with the reason that `QRect` and 
`QRectF` have been working like this since the beginning and there is a 
lot of software that can be broken, which is a really fair argument! 
Still, it won't make the issues go away...

In 6.6, kwin (except some effects) has been ported away from `QRect` and 
`QRectF` with a considerable success. kdecoration is the next candidate 
to switch away from those two.

The new rect helpers can be found at 
https://invent.kde.org/plasma/kwin/-/blob/master/src/core/rect.h?ref_type=heads.

I would like to propose adding a new library, e.g. kprimitivetypes, that 
would host `KRect` and `KRectF`. There is a slight challenge with KF 
though. It will be nice if KConfig and maybe other tier 1 libraries are 
able use `KRect(F)`. In order to achieve that, the new library will need 
to live either outside of KF or perhaps there could be tier 0 in KF?

Thoughts?

Regards,
Vlad


More information about the kde-devel mailing list