分数布局

niri 中有两个主要的坐标空间:物理空间(每个单独输出的像素)和逻辑空间(所有输出共享,考虑每个输出的缩放比例)。 Wayland 客户端主要在逻辑空间中工作,它是进行所有布局的最方便空间,因为它已经包含了输出缩放因子。

然而,许多元素需要以整数物理坐标进行大小或定位。 例如,Wayland 顶层缓冲区(toplevel buffer)假设放置在输出设备上的整数物理像素位置(WaylandSurfaceRenderElement 会帮你实现)。 边框和焦点环的宽度也应等于整数个物理像素,以保持清晰(更不用说 SolidColorRenderElement 不会对分数像素位置的线条进行抗锯齿处理)。

整数物理坐标并不一定对应于整数逻辑坐标。 即使比例因子为 2,物理坐标为 (1, 1) 的像素在逻辑坐标上也会是 (0.5, 0.5)。 当比例因子为分数时,这个问题会变得更加严重,因为大多数整数逻辑坐标会落在分数物理坐标上。

因此,niri 的大部分布局都使用分数逻辑坐标。 但是,需要非常小心地保持元素与物理网格对齐,以避免出现以下问题:

  • 边框宽度交替加粗/减细 1 像素
  • 边框在某些位置会超出窗口边缘 1 像素
  • 圆角周围有 1 像素的间隙
  • 调整窗口大小时,窗口内容略微模糊
  • 等等……

niri 的处理方式是:

  1. 工作区中所有相关尺寸均根据当前输出比例四舍五入为整数物理坐标。这些尺寸包括边缘保留区、间隙、边框宽度和工作区域位置等。

    需要注意的是,这些数字在逻辑空间中仍然是小数,但在物理空间中则对应于整数像素数。 舍入方式类似于:(logical_size * scale).round() / scale。 每当工作区移动到具有不同比例的输出(或输出比例发生变化)时,所有尺寸都会根据其原始配置值重新舍入,以与新的物理空间保持一致。

  2. 视图偏移量和各个列/平铺单元渲染偏移量不会四舍五入到物理像素,而是:

  3. tiles_with_render_positions() 函数在返回平铺单元位置时会将其四舍五入到物理像素值。
  4. 自定义着色器(例如打开、关闭和调整窗口大小)也会注意保持位置和大小与物理像素相等。

其理念是,每个平铺单元都可以假定其渲染位置为整数物理坐标,因此,当移动平铺单元位置(例如,移动边框宽度,也四舍五入为整数物理坐标)时,新的位置仍然保持整数物理坐标。 由于间隙、边缘保留区和工作区域也同样进行了四舍五入,因此布局的其余部分也遵循相同的逻辑。 这样,只要整个布局位于整数物理坐标上(平铺单元位置的四舍五入有效地实现了这一点),它就能始终保持对齐。