MyGit

v0.1.6

YaLTeR/niri

版本发布时间: 2024-05-18 19:35:33

YaLTeR/niri最新发布版本:v0.1.8(2024-08-10 20:40:27)

Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

We've now got a small setup showcase thread, be sure to check it out!

And here are the improvements from the last release.

Gestures

In this release, I added mouse gestures for resizing and scrolling the view. I also made a wiki page listing all existing gestures.

Interactive Window Resizing

You can now resize windows interactively with a mouse (yes, finally). Both by edge-dragging windows with client-side decorations, and anywhere on a window by holding Mod together with the right mouse button.

To complement this, there are two new double-click gestures: double-clicking a resize will expand the window to the full monitor width, or reset the window height to take up all available space, depending on the edge that you double-click. Thanks @FreeFull for suggesting these gestures!

Resetting the window height is also available as the new reset-window-height key binding.

https://github.com/YaLTeR/niri/assets/1794388/2598afdc-4520-4f85-8e95-ddd62aa37000

Despite the ubiquity, interactive resizing proved quite tricky to implement with plenty of edge cases (tiling makes it harder since multiple things need to coordinate together). The main challenge stems from the fact that when resizing a window by the left edge, its right edge should stay in place, which means that the window itself must move to the left, strictly in sync with changing size. Throw into the mix slow windows (the red rectangle on the video), windows not strictly obeying the given size (e.g. terminals snapping to the cell grid), and multiple windows in a column (which must all resize together), and you've got a wild asynchronous cocktail.

There was even a Chromium bug involved in this one, and a similar Firefox issue is waiting on a recent GTK 3 update.

Mouse View Scrolling

Holding Mod and the middle mouse button (scroll wheel) will now let you scroll the view. This uses the touchpad swipe gesture code with all its decelerated spring animation goodness, but makes sure that the spot that you "grabbed" stays locked to the mouse cursor.

https://github.com/YaLTeR/niri/assets/1794388/8464e65d-4bf2-44fa-8c8e-5883355bd000

Quite embarrassing how long it took me to come up with this one, considering I am primarily a mouse user.

Functionality

This release also adds some nice new functionality.

Named Workspaces

You can now declare named workspaces in the config.

workspace "browser"

workspace "chat" {
    open-on-output "DP-2"
}

Unlike normal (dynamic) workspaces, named workspaces are persistent (they are not deleted when they have no windows), but otherwise they behave just like normal workspaces: you can reposition them and move to different monitors.

Actions like focus-workspace or move-column-to-workspace can refer to workspaces by name in addition to by index. Also, you can use the new open-on-workspace window rule to make a window open on a specific named workspace:

// Declare a workspace named "chat" that opens on the "DP-2" output.
workspace "chat" {
    open-on-output "DP-2"
}

// Open Fractal on the "chat" workspace.
window-rule {
    match app-id=r#"^org\.gnome\.Fractal$"#
    open-on-workspace "chat"
}

You can find a few more details on the wiki page.

Named workspaces should mostly solve the "shove a bunch of windows on correct monitors at startup" problem while working seamlessly with the dynamic workspace system. Thanks to @algernon for implementing this!

IPC Improvements

The new niri msg output command lets you apply transient output configuration changes. It uses the same syntax as the config file, e.g. niri msg output eDP-1 scale 2. These changes will persist until you edit the output settings in the config file (or restart niri).

While adding this, I also made output names case-insensitive, both for niri msg output and for the config file, which should make things less annoying.

Additionally, @rustysec added a niri msg workspaces command which will be extra useful now with the introduction of named workspaces:

┌ ~
└─ niri msg workspaces
Output "DP-2":
   1 "chat"
   2 "browser"
 * 3
   4

Output "eDP-1":
   1 "notes"
 * 2
   3

Like with other IPC commands, you can use the --json flag to get the same data in a machine-readable form.

New Window Rules

You can now set focus-ring and border properties in window rules to override them for specific windows.

The new is_active_in_column matcher, added by @TheZoq2, can be used to make a magnifier-like window layout:

window-rule {
    match is-active-in-column=false

    min-height 100
    max-height 100
}

Finally, the new at-startup matcher will match during the first 60 seconds after niri startup. You can combine it with open-on-output or open-on-workspace properties to put windows where they belong when starting the session, but not afterward. I found it quite useful for e.g. browsers where I want new windows to open normally as I go on with my day, rather than keep spawning on the same monitor and workspace.

// Open Firefox maximized on the "browser" workspace, but only at niri startup.
window-rule {
    match at-startup=true app-id=r#"^org\.mozilla\.firefox$"#

    open-on-workspace "browser"
    open-maximized true
}

Debugging Features

There are a few new debugging features:

Eye candy

Of course, there are also new eye candy features!

Rounded Window Corners

Niri can now do corner rounding, a clear must-have feature for any self-respecting Wayland compositor. I've got quite an extensive implementation here, actually. Let's take a look.

You set the radius with the new geometry-corner-radius window rule.

By itself, it doesn't clip the window but merely informs elements like the border and the focus ring which window radius they should assume. This means that you can keep using client-side-decorated windows with their own rounded corners and shadows, and have the borders drawn with the right radius.

window-rule {
    geometry-corner-radius 12
}

This sets the radius of the window geometry—the inner radius of the border. The outer border radius is computed automatically taking the border width into account.

You can even set a separate radius for every corner, for example, to match GTK 3 applications:

window-rule {
    match app-id="^gnome-terminal-server$"
    geometry-corner-radius 8 8 0 0
}

No, I don't particularly see anyone going out of their way to set this up for every window.

Next, the new clip-to-geometry window rule will make niri actually clip windows to their geometry, including the geometry-corner-radius that you have set.

window-rule {
    geometry-corner-radius 12
    clip-to-geometry true
}

Combine this with prefer-no-csd to get the classic rounded corner setup that works on all windows:

prefer-no-csd

layout {
    focus-ring {
        off
    }

    border {
        width 2
    }
}

window-rule {
    geometry-corner-radius 12
    clip-to-geometry true
}

All of this works correctly with subsurfaces, windows blocked out from screencasts, transparency, resize and other animations. And whenever possible, there's no overhead: opaque regions are preserved (except for the corners themselves), and even overlay plane unredirection still works for subsurfaces completely inside the clipped geometry!

Tricky Cases Opaque Regions Unredirection

Screen Transition

I added a do-screen-transition action which lets you switch between light and dark, or between different themes, smoothly like in GNOME Shell.

https://github.com/YaLTeR/niri/assets/1794388/aa779179-2ad0-4e17-82af-a802b8d32094

The key is to make sure the applications themselves switch their theme without animation and as fast as possible, then niri's own screen transition will make it look nice and synchronized.

If your apps take just a bit too long to switch, you can increase the delay during which the screen is frozen (defaults to 250 ms):

niri msg action do-screen-transition --delay-ms 500

Animation Custom Shaders

Finally, for something more advanced. I'm experimenting with the ability to set custom shaders for animations. Currently, I added support to all three base window animations (open, close, resize).

No, not those shaders.

For example, you can use a custom shader to change the default crossfade resize to an animation that crops the window when it is growing, and crossfades only when it is shrinking. This looks nicer for the text-heavy terminals since it avoids visually stretching the text.

https://github.com/YaLTeR/niri/assets/1794388/438f51c1-4ad7-4b86-963e-6842a732c060

For the closing animation, I made a shader that makes the windows fall down and rotate, inspired by the S rank animation from osu!lazer:

https://github.com/YaLTeR/niri/assets/1794388/9adf2919-7994-454d-a4be-08b701b40d0b

And for the opening, I made a simple expanding circle example:

https://github.com/YaLTeR/niri/assets/1794388/27a238d6-0a22-4692-b794-30dc7a626fad

The way you make these shaders is by writing a GLSL function:

animations {
    window-resize {
        custom-shader r"
            vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
                vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo;
                vec4 color = texture2D(niri_tex_next, coords_tex_next.st);
                return color;
            }
        "
    }
}

Like all other settings, custom shaders are live-reloaded as you edit the config. I've got detailed documentation with many examples, including all shaders above, in this folder.

Other improvements in this release

相关地址:原始地址 下载(tar) 下载(zip)

1、 niri-0.1.6-vendored-dependencies.tar.xz 52.79MB

查看:2024-05-18发行的版本