Continuation of discussion for zoom/magnifier interface and impl in #3246 #3285
Replies: 40 comments 129 replies
|
Having done some more quick research, here's a new design for the interface on bind/ipc-action side: niri msg action set-zoom-state --<param> <change> <option<output_name>>IPC actions do tend to take So you will still have pass queries through the old interace. |
|
Just pushed another patch on the PR that implements the zoom center-lock. I call it freeze now, because... I started with that when it was mentioned in the PR thread and didn't get around to changing it. Usage: output "<name>" {
zoom {
freeze // locks the zoom-center/viewport so cursor is free to explore
}
}niri msg output <name> zoom freeze true|falseI don't know when I'll get to this: |
|
Currently, niri actions tend to be quite granular. More examples to drive my point home: Also, I think toggling zoom freeze should be an action, rather than an Freeze, on the other hand, is very action-like — you toggle it because you want to use it for probably just a few seconds, and then toggle it off. As opposed to it being a setting that you enable and then stick with for a while because you prefer it. Unless I misunderstand how the freeze feature works. I'm on an old-ish commit of the pr, as I'm currently more satisfied with it than with the current iteration, when it comes to the ipc. And so I might be talking out of my ass above. |
|
I can see where you're coming from about niri allowing granular actions. And yeah, the config options do seem a bit bloated. There is such as thing as too much configurability. Maybe instead of making it all per-output, I should make just zoom factor per-output and let everything else be set via a new namespace in But about niri msg output, I disagree about them being for finalistic action, it's help literally says 'Change output configuration temporarily'. Though that begs the question, would changes to output config made like that survive config reload (for users who do dynamic theming)? I think not, so decoupling from that seems a good idea in general. How does this look then? cursor {
scale-with-zoom
}
zoom {
default-factor 1.5
movement "cursor-follow" // or "edge-pushed"
threshold 0.05 // 0 to 1 float
}niri msg action toggle-zoom <option<output_name>>
niri msg action toggle-zoom-freeze <option<output_name>>
niri msg action set-zoom-factor <float_or_int> <option<output_name>>
niri msg action set-zoom-movement <change> <option<output_name>>
niri msg action set-zoom-threshold <float_or_int> <option<output_name>>For queries niri msg focused-output
Output "Chimei Innolux Corporation 0x1406 Unknown" (eDP-1)
Current mode: 1920x1080 @ 60.002 Hz (preferred)
Variable refresh rate: not supported
Physical size: 310x170 mm
Logical position: 0, 0
Logical size: 1280x720
Scale: 1.5
Transform: normal
Zoom:
Factor: 1.5
Movement: cursor-follow
Threshold: 0.01 or 1%
Frozen: true
Available modes:
1920x1080@60.002 (current, preferred)
1920x1080@40.002Or maybe this: niri msg zoom-state
Factor: 1.5
Movement: cursor-follow
Threshold: 0.01 or 1%
Frozen: true
That's my bad. I didn't mention the |
|
Yeah, I like the idea of a zoom section, that applies globally to every output, instead of having to configure it separately per each. But more importantly than what I like, I think it makes more sense too: in no world will someone prefer cursor-follow on one monitor, but edge-pushed on another. I say this in fear of the Usecase Man™ appearing, but I feel this is super reasonable to not anticipate. The
I guess so, but even still, freezing zoom sounds to me more like an action you are doing, rather than changing your monitor's configuration. You are operating on a feature of the compositor, rather than a feature of your monitor, is how I would put it. I wonder if Queries look fantastic 👍 Ah nice, there's an action for it too? In that case, is there a need to duplicate it under |
|
Would you also want an IPC event for zoom state changed? It would defined like: enum Event {
...
ZoomStateChanged {
output: String,
change: ZoomState,
}
} |
|
It's awesome! And it's works very fine. But there are things worth paying attention to:
|
|
I think I'm gonna remove the entire zoom {} block too. Nobody cares enough about default zoom factor, threshold isn't really too customizable since there's only a few good values for it. For movement, we can probably throw it into a misc option like prefer-no-csd or something. We'll still have For IPC, we will: niri msg action set-zoom-factor <float_or_int> <option<output>>
niri msg action set-zoom-movement <name> <option<output>>
niri msg action toggle-zoom-freeze <option<output>>
niri msg --json zoom-state <option<output>>
{factor: float_or_int, movement: "cursor-follow|edge-pushed", is_locked: bool} |
|
I have a suggestion that I didn't see discussed yet in the PR: What do you think about dynamically changing the mouse sensitivity based on the zoom level so that your "perceived" mouse sensitivity is kept consistent? Typically when you zoom in, your perceived sensitivity is much higher. This feature could help you get fine grain control to click something specific if you use high sensitivity. |
|
Not sure if it's something others have experienced, but with the recording-while-zoomed thing, I guess that's the same behaviour you get when you share your screen over a tool like MS Teams or Slack or Zoom or whatever. For work, whenever I need to demo something on my screen (not using Niri currently), I normally make sure I'm zoomed out beforehand, so as not to disturb/confuse anyone watching the feed, as they wouldn't be expecting the magnification in order to see what's on the screen like I would. |
|
@zgibberish For everyone else; the implementation has gone through a complete re-write based on patterns I observed from both Niri and cosmic-comp, though end user experience should not change much. The current interface: zoom {
movement-mode "cursor-follow|on-edge|centered"
increment-type "linear|exponential"
}
cursor {
scale-with-zoom
}
binds {
Mod+Alt+Equal { set-zoom-level "+0.1"; }
Mod+Alt+Minus { set-zoom-level "-0.1"; }
Mod+Alt+WheelScrollUp { set-zoom-level "+0.1"; }
Mod+Alt+WheelScrollDown { set-zoom-level "-0.1"; }
Mod+Z { set-zoom-level "1.0"; }
Mod+Shift+Z { toggle-zoom-lock; }
}niri msg action set-zoom-level (+1.0|-1.0|1.0) "output_name"
niri msg action toggle-zoom-lock "output_name"
niri msg zoom-stateI removed a couple of options and actions, as well as the new event. Too much configuration that I feel is rarely messed with, and you can always query the zoom-state so the event felt redundant. I also implemented dynamic sensitivity based on zoom level. Or at least tried to, I don't know if I did it right, since I couldn't feel any difference. |
|
Omg :DDD the new changes are fantastic!! You even added exponential incrementing? One one hand I think I personally want it, on the other I'm not sure if it needs to be in core. But I feel it is such a common want that yeah, probably it's okay for it to be in core. OMG!!! DYNAMIC SENSITIVITY!!! I'm so happy 🥹 updating right now to test all the new changes! |
|
This works so well it almost makes me cry. I think the new API is excellent and it also means no need for a separate wrapper script here either. The exponential mode is pure 😙🤌. Fantastic work. |
|
@Axlefublr and @zgibberish |
|
Some thoughts Sooo, ahh... Idk, toggle-zoom as it was before would be bad UX, but I want in future have something to toggle zoom level between 1 and some value. What about With animations I suppose it will work veeery nice and beauty I've added in my config this lines and have veeery nice UX for now with mouse that have additional two buttons under my thumb:
Bug:
P.S.: Bug:)
P.P.S.: Despite above issues and so on, for now as for me this feature works as I wanted and I am so happy and satisfied that someone implemented it and you did it very good as for me! |
|
A couple more changes were pushed. Now everything should be fixed. Pretty sure. I hope. About 80% certain. |
|
On a7103d7, my system often freezes when using Steam, can anyone reproduce this? |
|
I fixed a regression which re-introduced jitter on the cursor when moving the zoomed viewport in the on-edge movement mode. I did not test for that when I patched the issue with Steam and LibreOffice. Sorry about that! I also cherry-picked some of the refactoring commits from the Blur PR. But with this, I consider this PR pretty much stable and finished from a feature and integration perspective. If anyone notices any performance issues or has suggestions for profiling it, please let me know. As always, thank you for testing out my work. Hope you enjoy the feature. |
|
Has anyone noticed this issue where the mouse cursor jumps when pushed against the bottom & right edges? 2026-04-01.13-50-44.niri.magnifier.cursor.jumping.mp4But it doesn't show in screen recordings (???) |
|
I'd like to ask if people are happy with the texture filters and how they are currently being applied. Especially with the Niri drawn UI overlays like the help panels, exit confirm dialog, error notification, and mru window ui. These are never rendered with zoom applied but due to how I apply the texture scaling will still receive texture filter scaling when zoomed in. |
|
So cool.! Especially this works with screenshot-ui. This way I can use screenshot ui to 'freeze' the screen and use the magnifier to do some pixel level inspection for the video buffer. There's one small keybind issue: I'm using the example config Mod+Alt+WheelScrollUp { set-zoom-level "+0.3"; }
Mod+Alt+WheelScrollDown { set-zoom-level "-0.3"; }
Mod+Z { set-zoom-level "1.0"; }
Mod+Shift+Z { toggle-zoom-lock; } // locks focal center, will also make it lock leveland Mod+Z and Mod+Shift+Z don't work when screenshot-ui is present. |
|
One thing I notice is that when you are zoomed in, the cursor movement is slowed down, is there any way to configure it so that zoom level doesn't affect how fast the cursor moves around the desktop? |
|
Can you update the docs for config options on the PR? I'm trying the latest commits (d72d94c) but the options I've used before are now invalid > niri validate
Error: × error loading config
├─▶ error parsing
╰─▶ error parsing KDL
Error: × failed to parse included config
╭─[config.kdl:11:1]
11 │ include "rules-window.kdl"
12 │ include "zoom.kdl"
· ───┬───
· ╰── node starts here
13 │
╰────
Error: × error parsing KDL
Error: × unexpected node `zoom-focal-pan`
╭─[zoom.kdl:12:1]
12 │ animations {
13 │ zoom-focal-pan { spring damping-ratio=1.0 stiffness=2500 epsilon=0.0001; }
· ────────────────────────────────────────┬───────────────────────────────────────
· ╰── unexpected node
14 │ zoom-level-change { spring damping-ratio=1.0 stiffness=2500 epsilon=0.0001; }
15 │ }
╰────
Error: × unexpected node `zoom-level-change`
╭─[zoom.kdl:13:1]
13 │ zoom-focal-pan { spring damping-ratio=1.0 stiffness=2500 epsilon=0.0001; }
14 │ zoom-level-change { spring damping-ratio=1.0 stiffness=2500 epsilon=0.0001; }
· ────────────────────────────────────────┬───────────────────────────────────────
· ╰── unexpected node
15 │ }
16 │
╰──── |
|
How many people really want the scale-with-zoom setting, and how much do they want it? Is it fine if we just pick one of either scaling the cursor or not in a hard-coded fashion? |
|
Can we have screen zoom related actions be allowed when screen is locked? Since the zoom gesture works when locked, it would make sense that the actions triggered with keybinds also work there. |
|
I just noticed that my non-primary monitor doesn't render anything but the cursor and most builtin compositor ui when zoomed in. screenshots and window capture work flawlessly, but screen capture is also affected (presumably because that doesnt rerender anything). it doesn't happen when its the only active output, and my primary monitor works fine in any case. 2026-05-23.15-49-26.mp4 |
|
I was testing the latest commit (at the time was c9bab5b) and was getting many random freezes while zooming, it was like that time with Steam, but now in Zen browser, not sure if it's exclusively in Zen, I haven't done much extensive testing. The screen would just freeze, all input stops working, but I could still get notifications, and audio still plays. Right now I downgraded to d72d94c, no issues there. |
|
Are there any plans to add shaders like KDE's zoom's pixel shader or the new with plasma 6.7 upscaling shader? |
|
Ever since zoom animations couldn't be disabled, I've been experiencing an issue I describe fully in my blog post, in this section. I mentioned it half-handedly in the niri discord; yalter expressed “this is definitely not how it should work” |


Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary:
The PR in the title (#3246) is an implementation of zoom/magnification for Niri.
It uses the same pipeline as the overview pan out. Basically, I pass all the render elements through a zoom transform, and added new variants to niri_render_elements! macro to generate Into impls for the appropriate variants on that type.
The PR got a lot of traction, discussion and feedback. It's over 100 comments now! So I brought the discussion over here now.
All reactions