-
-
Notifications
You must be signed in to change notification settings - Fork 662
Feat/cursor zoom #3246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/cursor zoom #3246
Conversation
16f64e0 to
7d3618a
Compare
|
Also, I'm unsure which of the relocated variants are completely neccessary for this in the niri_render_elements! macro. |
|
Thank you so much for doing this! Notes from testing:
For usability, actions to zoom in, zoom out, and reset zoom would be good, an IPC request to query the current zoom factor too, maybe. I can do those later in a follow-up PR if you want. |
|
Thanks for the feedback @miku4k!
Yeah, I really didn't expect to be able to just get it work so simply with the overview. Niri's render pipeline seems insanely well architected! On the flip side, it's also so... obscure? complicated? or something. Figuring out what the relevant parts were took a while. Then I just gave up and looked at what overview was doing, did some copy paste and it worked!!??
I use DMS with everything thrown into the overlay layer so it worked out-of-the-box for me. Will try to see if I can get background layer-shell surfaces to co-operate.
Yeah that was a deliberate choice. Since how you interact with them doesn't change based on screen magnification right? I am open to feedback on changing that though. Personally though, quite happy with the feel of it for now.
Will actually look into that. I thought that would just be a limitation of zoom straight up. I didn't other DE's did anything to sharpen or improve resolution of magnified render elements.
I didn't want to change IPC too much, since I was torn on making it a simple Action variant as it is, or making it a Request variant. Decided to make it work first then worry about interface stuff with maintainer feedback. |
|
To note, in it's current implementation this probably applies the same zoom/magnification across all outputs/monitors. |
|
I saw the PR and tested it right away, it's a great feature, thank you so much for working on it, I have some feedback + things I would like to see in the final version, hope this can be useful
|
I don't know about other desktops, but I have seen some image programs using both linear/nearest algorithms, depending on the zoom factor. Something like:
In my experience this is what works better most of the times. Ideally, the threshold should be configurable. |
Slight correction to my previous statement, I forgot what layer my clock widget is on, the bottom layer is affected too. I guess they're separate because one's above and one's below windows.
I suppose it makes some sense for the screenshot UI, and the MRU, but zoom is primarily an accessibility feature, and someone who needs zoom likely won't be able to read the small text in those UIs. I think zooming the screenshot UI is kinda problematic implementation-wise, as far as I know, it screenshots whats finally rendered, so the selection would be inaccurate.
I just researched a bit, and StackOverflow says Windows seems to use a pixel art scaling algorithm based on xbr. I might have just hallucinated Hyprland using a special algorithm, because I couldn't actually find any evidence of that, I'll admit it's been a while. I'm more certain about Kwin because it's part of a full desktop environment. Also saying that, you could check what cosmic-comp does.
+1, I'm thinking like something linear, 0.1 seconds.
+1, It would require keeping the center position independent of the cursor; the calculations currently directly use the cursor position. Still sounds straightforward I think. I think that's overcomplicating it a bit. |
|
This is awesome! 🚀🚀🚀 Let me ask, b/c I could not see exactly from the recording over in this thread and also not from the comments above:
Thanks! |
@bertbesser Yes, you can interact while zoomed in |
|
Thank you all for the amazing response and feedback! I'll be bothering you all for more. I just pushed a patch to address some of it. But also, has anyone tested it on multiple monitors yet?
Both background and bottom layer should work now. Do tell if anything else is not working in that vein.
Ah yes, I didn't fully consider that. Yeah, I've read the discussion over on cosmic about this.
Will do. I was actually moved into working on this because I wanted Hyprland's cursor:zoom_factor's effect in Niri! The script I used in the showcase I posted on #1024 was something I built for Hyprland. So when you mentioned it using a sharpening effect really tripped me up, since I'd never noticed anything of the like there. Can you link the stack overflow page and any other references I can use for this?
I've was actually looking into that before I decided to checkpoint and make the PR for getting feedback and approval. It's in the works.
Actually this would need some refactoring on my part, since right now I don't actually store any state other than the zoom factor. This would require having an independent zoom_center variable that would be passed into apply_cursor_zoom instead of the cursor_pos. Of course I would need to do it anyway, for better IPC and supporting other features in the future, but I don't want to commit to that yet before I get some feedback on multi-monitor behavior.
Yeah having two algorithms just for differing zoom_values seems a bit much. |
|
Also I just had an idea, would be great if this uses logarithmic scaling, so zooming steps feel smoother. |
a6eaf27 to
b4c4ca8
Compare
I feel like we should leave that up to user scripting, and only provide the setter, getter, increment and decrement options. |
|
|
Wow, this is excellent, I'll give it a go today. I had started on my own implementation of this but you're far further along than I was. Can we have the "mouse follows cursor" / "mouse pushes cursor when at edge" be switchable? I much prefer the former, but some prefer the latter. |
|
Just gave it a sneaky test - works rather well, very smooth performance wise. A little blurry (as mentioned). I like how it handles when the mouse approaches the edge of the screen, where the cursor is allowed to drift away from the center of the screen to compensate, functioning in a similar way to Gnome and Kwin does, which I think is a good way to go. The interaction with the overview is a little weird. Gnome 3 for the longest time had the exact same issue with their overview/app dashboard. The handling there may need some more thought. Unfortunately I don't have a second monitor to test multi-monitor use. |
|
I have literally been holding off on Niri due to missing a feature like this. I have multiple monitors including a 32:9 ultrawide, I'd be glad to take a look at this. |
Yes, clone this fork and pull the "feat/cursor-zoom" branch. Then compile using: After which, the Once logged in, you can then use IPC commands to change the zoom factor, eg: |
Thank you. I'll try to put this PR through it's paces tonight/tomorrow and see what I can break. |
|
I've been testing the latest build for a bit, the background layer zoom works now, but I also noticed that the background doesn't move when switching between workspaces, to be honest I like it this way more 😆, but I don't think it is intended behavior. Uploading 2026-01-16 16-33-17 niri mag pr weird background issue.mp4… |
I tested that right now, and wow it's weird. Should I do something about that? Or would people prefer it that way...? Also general question: Do we want the sharpened scaling with nearest neighbor or linear scaling to be configurable? Or just have whichever looks best stick with only that? |
|
I prefer it personally, but it is extra side effects / behavior on top of a feature. pr baggage, basically. so better to fix if it's viable to do so |
|
agreed! I think increment/decrement is in the territory of “too nice”. just get and set is sufficient. |
|
Thanks @my4ng! I don't really know what 'as expected' means here, so would you mind clarifying?
The weird behavior with overview is something @zgibberish already mentioned. I pushed a patch for that. See if that fixes it. Thanks for the code suggestion! I just check the IPC again, and I have to agree with you and @Axlefublr. Niri usually never provides any incr/decr actions only getters/setters. |
|
Yeah I agree, a "user-land" program should be deployed that can handle stuff like scrolling with the mouse wheel and applying whatever increment factor is desired etc. Niri should just provide a robust solution for the actual magnification. |
|
Hi again, I'm running on the latest commit, the background sticking when switching workspaces behavior is still here 2026-01-16.19-19-52.niri.mag.pr.video.2.mp4 |
Yes so when the zoom is set, both monitors are zoomed in, centred around the cursor position at the moment of the IPC action. For example, if the cursor was at the top left corner of the left monitor when a zoom level of 2.0 is set, assuming equal output size, then the right monitor will display what was the top right quarter of the left monitor. But also the zoom is partially clipped: the left monitor is clamped to never show the content of what was in the right monitor, but the right can show what was on the left monitor. IMG_9088.movPersonally, I am not sure if this cross-monitor zoom is the desired behaviour, as niri has quite a strong sense of isolation between each monitor, e.g. you cannot have a floating window spanning two monitors. It doesn't make much sense from an accessibility point of view either. |
|
Just tested the latest revision again, with it now set up as a shortcut. I think logarithmic zooming would definitely be very useful. Once you zoom in by more than 3x or so, a change of 0.2 becomes very minimal and so it's unnaturally 'slow' to adjust in/out once zoomed in. Logarithmic would feel much more natural. Either that, or perhaps allow deltas of a percentage (+/- 10% for example). Fantastic work though, the nearest neighbour implementation works great, and it already lacks a few bugs that Gnome's implementation has always (and continues to have). I'll leave the IPC discussion for others for now as I'm quite to Niri. |
GAH i love it that was pretty funny
yeah.. I this kinda turned into a full on discussion rather than the average PR thread, which can make it harder for future participants to follow, I think this was partly because people started to notice flaws and discuss about optimal designs more, since we had a working implementation to try now.
@garfunkel this can be done with user scripts, I made this nushell script for logarithmic zooming, you can try it https://gist.github.com/zgibberish/4a19e0829ac17b9e89fa9344ef143e86 Note I haven't updated it to use the latest IPC impl tho, it should work on 14ae109 |
|
Big agree with @miku4k. Being required to call indeed would be wonderful. I'm very partial (maybe even whole!) to this api. As for the overall
Yeah I can understand if it feels a bit exhausting! We've even overtaken the infamous blur pr at this point. But I think this just goes to show that this is a complicated enough feature that it warrants so much discussion. Our united goal, after all, is to make niri the best it can be :D |
|
@miku4k Thank you for the kinds words. Getting the edge-pushing to work though, was real head-scratcher, since I'm not really well-versed in graphics math. About the IPC actions, I'll add back those two actions then since it's preferred. Also get rid of the toggle-zoom action in favor of just letting Looking back on my notes, the animations really only need defined start and end points, so integration with that would only work for the toggle, i.e, significant changes to the zoom factor. Like overview and window movements. Using them for large amounts of continous changes like with pinch updates (again, my script on the tracking issue) would be... not great. I don't think so at least. I'm working on locking the zoomed viewport right now. P.S: I created #3285 for futher discussion of this. We can bikeshed further over there! |
2234551 to
5def8d7
Compare
5def8d7 to
973d580
Compare
- Code cleanup seems to keep jumping out at me
e3cd310 to
6237be1
Compare

Adds a new ipc action set-cursor-zoom that takes a floating point value and applies a zoom transform to the entire compositor.
Tracking issue #1024