Bug 479703 - Expose global Wayland screen offsets of top-left of all given KDecoration2 geometries for pixel-snapping with fractional scaling
Summary: Expose global Wayland screen offsets of top-left of all given KDecoration2 ge...
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: decorations (other bugs)
Version First Reported In: 5.27.9
Platform: Other Other
: NOR wishlist
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-12 18:02 UTC by Paul McAuley
Modified: 2024-01-16 14:56 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Paul McAuley 2024-01-12 18:02:24 UTC
Hello, 

I am the developer of a C++ window decoration (https://www.github.com/paulmcauley/klassy). In my window decoration I have attempted to implement a pixel-snapping algorithm so that lines in icons (especially horizontal/vertical lines) and other painted items are sharp -  this works on integer scale levels (and by fluke works on scales with a fractional part of 0.5 because I happen to multiply all my geometries by a factor of 2), however, it does not work properly on all fractional scales on Wayland. 

This is because I am currently assuming that the QPainter device geometry of the top-left of the titlebar is a zero pixel boundary reference point (https://github.com/paulmcauley/klassy/blob/3490b94f721d9cfab4d4cf4691fbfcac8570637d/kdecoration/breezebutton.cpp#L228C2-L228C2) . However, on Wayland this is not always the case with fractional scaling.

Therefore, to implement pixel snapping properly with fractional scaling on Wayland, I would kindly request some additions to the KDecoration2 API. Namely, provide functions returning a QPointF that gives the offset position (call it e.g. <geometry>ScreenPos() ) in global Wayland co-ordinates from the current screen position 0,0 to the top-left of a given geometry QRectF. This offset would not be an integer pixel offset, but rather an offset that would need to be floating point for Wayland in the same co-ordinate system used by Wayland, as Wayland co-ordinates are relative to 100% scaling dimensions. 

This would be a most welcome additional piece of data to complement the following <geometry>s provided with KDecoration2, each with their own added "<geometry>ScreenPos() " offset function:

KDecoration2::DecorationButton::geometry() (this one is the most useful as it could be used with standalone buttons as well)
KDecoration2::DecorationButtonGroup::geometry() 
KDecoration2::Decoration::rect()
KDecoration2::Decoration::titleBar() (potentially useful in case want to draw on titlebar directly with custom graphics) 
KDecoration2::DecorationShadow::innerShadowRect() (could potentially be useful for drawing automatic sharper window outlines which are currently done as part of the shadow, though would need this offset available before a shadow is provided by the decoration).

Thank you, 

Paul
Comment 1 David Edmundson 2024-01-12 18:36:29 UTC
We've jumped a few steps, let's back up from proposing solutions. 

All decoration content is snapped to the pixel grid when we render. As long as you render at the provided for and align within the buffer you write to, everything should be fine. If that's not the case, we need to investigate.
Comment 2 Paul McAuley 2024-01-12 20:04:10 UTC
(In reply to David Edmundson from comment #1)
> We've jumped a few steps, let's back up from proposing solutions. 
> 
> All decoration content is snapped to the pixel grid when we render. As long
> as you render at the provided for and align within the buffer you write to,
> everything should be fine. If that's not the case, we need to investigate.

OK, thanks for your reply David. I'll double-check on the latest Plasma code at the weekend and check to see if decoration button icon snapping is good at all scales and report back. Admittedly, my understanding is from when I last looked at this in detail at the time of Plasma 5.26.

Would you know in what release this pixel-snapping of decoration was introduced? What reference geometry is snapped to a grid? I assume KDecoration2::Decoration::rect()? Is KDecoration2::DecorationShadow::innerShadowRect() also snapped?

Regards
Comment 3 Paul McAuley 2024-01-16 14:56:33 UTC
I can confirm that my pixel-snapping algorithm is now working for all fractional scales on Plasma 5.27.9 and all are sharp! Good job - snapping the decoration must have been a change in 5.27, or one of its point-releases, that went by me.

 I also changed my zero whole-pixel reference-point to be the deviceTransform  map of KDecoration2::Decoration::rect().topLeft(). I hope this is the correct snapped point - would be good to confirm.

( https://github.com/paulmcauley/klassy/commit/3d829ae8a179463dbaee8faa9321a0df254040a3 )



(Also, ignore my previous comment on innerShadowRect() - I was writing away from a computer and had forgotten the detail on how a shadow was implemented)