Niri 26.04: 스크롤형 타일링 Wayland 컴포지터

8 hours ago 2
  • 스크롤형 타일링 Wayland compositor에 배경 흐림, 스크린캐스트, 렌더링, 입력 처리 전반의 개선이 더해지며 완성도가 커짐
  • 배경 흐림이 메인라인에 포함되어 ext-background-effect를 지원하는 창과 layer-shell 요소가 별도 niri 설정 없이도 흐림을 요청할 수 있고, niri 쪽 규칙으로도 흐림을 강제 적용할 수 있게 됨
  • 스크린캐스트는 PipeWire와 wlr-screencopy 경로 모두에서 커서 처리, dynamic cast 시작 방식, IPC 조회와 강제 종료, 다중 복사와 자원 해제 문제까지 함께 다듬어짐
  • 렌더링 구조는 iterator 기반에서 push 기반으로 재구성되어 렌더 리스트 구성 속도가 주요 머신에서 2~3배, 오래된 Eee PC에서는 8배 빨라졌고 메모리 사용도 줄어듦
  • 구형 하드웨어와 입력 환경까지 손봐 오래된 Intel 시스템의 스크린샷·스크린캐스트, IME와 GTK 4 팝업 충돌, 고주사율 마우스와 태블릿 매핑, nested niri의 DMA-BUF 가속 등 실제 사용 범위가 넓어짐

핵심 변경점

  • GitHub 조직이 개인 계정에서 niri-wm으로 옮겨졌고, 관련 프로젝트도 함께 정리됨
  • 패키저 관련 변경도 포함됨
    • 최소 지원 Rust 버전이 1.85로 올라감
    • niri.service가 더 이상 niri 바이너리 경로에 /usr/bin/을 하드코딩하지 않음
    • dinit 서비스 파일 구조가 바뀜: 3bfa4a7

배경 흐림

  • 배경 흐림이 메인라인에 들어왔고, 창과 layer-shell 구성요소가 ext-background-effect 프로토콜로 흐림을 요청할 수 있음
  • 앱이 아직 ext-background-effect를 지원하지 않아도 window-rulelayer-rule로 niri 쪽에서 흐림을 켤 수 있음
    • 세부 설정과 제약은 Window Effects 문서에 정리되어 있음
    • niri에서 설정한 흐림은 올바른 geometry-corner-radius가 필요함
    • 복잡한 surface 형태에는 동작하지 않음
  • xray blur와 일반 blur를 함께 제공하며, 기본값은 xray blur임
    • xray blur는 배경화면을 한 번만 흐리게 계산하고 정적 이미지처럼 재사용해 훨씬 효율적임
    • 배경화면이 바뀔 때만 다시 계산됨
    • 애니메이션 배경화면에서는 효율 이점이 줄어듦
    • 새 layer matcher로 top, overlay 같은 레이어에만 일반 blur를 적용하도록 바꿀 수 있음
  • 흐림 기능은 렌더링 구조 변경이 필요할 만큼 구현 난도가 높았음
    • 일반 blur는 프레임 중간에 이미 렌더링된 픽셀을 다시 읽어 흐리게 만든 뒤 렌더링을 이어감
    • xray blur는 올바른 배경 잘라내기를 위해 창 위치를 렌더링 코드 전반에 전달해야 했음
    • Overview에서 xray blur를 지원하면서도 overview를 다시 렌더링하지 않는 성질을 유지해야 했음
    • 스크린캐스트 차단 창과도 함께 동작해야 했음
  • 흐림 없이 xray만 단독 사용할 수 있고, blur 색 띠 완화용 noise와 saturation 효과도 따로 활용 가능함
  • popups 블록으로 window rule 또는 layer rule에서 팝업 메뉴에도 투명도와 배경 효과를 적용할 수 있음
    • GTK 4의 has-arrow=true 팝업처럼 둥근 직사각형이 아닌 경우 모양이 어색할 수 있음
    • 웹앱이나 Electron은 Wayland 팝업을 쓰지 않아 niri가 처리할 수 없음
    • ext-background-effect를 직접 구현한 클라이언트는 더 복잡한 형태의 흐림도 다룰 수 있음

선택적 include

  • config include선택적 include가 추가됨
    • include optional=true "optional-config.kdl"처럼 쓰면 파일이 없어도 설정 로딩이 실패하지 않음
    • 파일이 없으면 매 설정 리로드마다 경고 로그를 남기지만 설정은 계속 로드됨
    • 나중에 파일이 생기면 감시 중이던 변경이 잡혀 자동으로 다시 로드됨
    • 파일이 존재하지만 문법 오류가 있으면 여전히 파싱 실패로 처리됨
  • include 경로에서 ~를 홈 디렉터리로 확장함
    • ~/file.kdl이 /home/user/file.kdl로 확장됨

포인터 워핑과 스크롤

  • 뷰를 스크롤하는 제스처 중 포인터가 화면 한쪽 끝에서 반대쪽으로 워핑되도록 바뀜
    • Blender와 비슷한 동작임
    • 모니터 가장자리 근처에서 시작해도 여러 창을 자연스럽게 계속 스크롤할 수 있게 됨

스크린캐스트 개선

  • niri의 스크린캐스트는 PipeWire 경유 xdg-desktop-portal-gnome 또는 wlr-screencopy 경유 방식 모두에서 개선됨
  • 창 스크린캐스트의 커서 처리

    • PipeWire에서 커서를 영상 프레임 안에 직접 그리는 방식 대신 커서 메타데이터를 지원하게 됨
      • 비디오 프레임에는 커서가 들어가지 않고, 커서 아이콘과 좌표를 별도 버퍼로 보냄
      • OBS나 브라우저 같은 소비 측이 커서를 직접 그리게 됨
    • 모니터 캡처와 창 캡처 모두에서 동작함
    • 창 캡처에서는 해당 창이나 그 팝업을 실제로 가리킬 때만 커서가 보임
    • 드래그 앤 드롭 아이콘도 함께 그려짐
    • 구현 과정에서 PipeWire의 메모리 손상 문제도 드러났고 수정됨
    • PipeWire 의도와 libwebrtc 같은 소비자 구현 사이의 불일치도 확인됨
    • 테스트한 환경에서는 정상 동작함
    • screenshot-window show-pointer=true로 창 스크린샷에도 포인터를 포함할 수 있음
  • Dynamic cast target 시작 방식 변경

    • Dynamic cast target은 키바인드로 스크린캐스트 대상을 즉시 바꾸는 기능임
    • 이전에는 시작 시 1×1 검은 픽셀 비디오 스트림으로 열렸음
    • 이제는 첫 실제 대상이 선택될 때까지 비디오 스트림 시작을 지연
    • Microsoft Teams에서의 짧은 1×1 비디오 문제를 피할 수 있음
  • Cast IPC

    • 현재 진행 중인 스크린캐스트를 IPC로 확인할 수 있게 됨
    • niri msg casts로 활성 캐스트를 볼 수 있음
    • event stream에서 cast events를 구독할 수 있음
    • Cast 객체는 종류, 현재 대상, 활성 상태를 제공함
    • PipeWire 스크린캐스트는 node ID를 제공하고, wlr-screencopy는 클라이언트 프로세스 ID를 제공함
    • DankMaterialShell은 이미 이 IPC로 스크린캐스트 표시기를 띄움
    • niri msg action stop-cast --session-id <ID>로 PipeWire 스크린캐스트를 강제 종료할 수 있음
  • wlr-screencopy 관련 한계와 수정

    • wlr-screencopy는 스크린캐스트와 스크린샷을 견고하게 구분하는 방법이 없어 일부 휴리스틱이 필요함
    • xdg-desktop-portal-wlr은 wlr-screencopy manager 객체 하나를 계속 유지해 종료 시점을 바로 알기 어려움
    • 이런 문제는 새 ext-image-copy-capture 프로토콜에서 해결되지만, niri에는 아직 들어오지 않음
  • 기타 스크린캐스트 수정

    • damage 복사 시 wlr-screencopy 클라이언트가 커서를 원치 않더라도 항상 포함되던 문제를 고침
    • damage가 있는 다중 프레임 복사를 동시에 요청할 때의 동작을 고침
    • 클라이언트가 종료됐을 때 등 일부 경우 niri의 wlr-screencopy 데이터가 해제되지 않던 문제를 고침
    • 기본 PipeWire 스크린캐스트 버퍼 수를 16에서 8로 줄임
    • pipewire-rs의 use-after-free 문제를 피하도록 구조체 필드 순서를 조정함
    • dynamic cast 대상을 창으로 바꿀 때 한 프레임 동안 z-order가 잘못되던 렌더링을 고침

애니메이션과 창 동작

  • 애니메이션 동기화가 더 정확해짐
    • niri는 개별 애니메이션을 따로 설정할 수 있지만, 서로 정확히 맞아야 하는 경우 동기화해 실행함
    • 창 크기 변경 애니메이션은 그것이 유발한 가로 뷰 이동 애니메이션과 동기화됨
    • fullscreen 또는 maximize 해제 시 뷰 이동 동기화가 빠져 창은 즉시 돌아오고 화면만 천천히 스크롤되던 문제를 고침
  • 특정 드래그 경로에서 다른 타일 창의 가로 이동 애니메이션이 건너뛰어지던 문제를 수정함
    • 최대화된 창을 드래그해 해제하고, 원래 떠 있던 창이면 다시 floating으로 돌리는 동작과
    • 모니터 가장자리 근처 드래그 시 좌우 workspace 스크롤 로직이 겹치며 생기던 문제였음
    • 수정 커밋: df3f3979e936ed6800b4fbd55843bb0fe2554f15
  • workspace 맨 왼쪽 열을 끌어냈다가 다시 놓을 때 원래 자리 대신 오른쪽에 들어가던 문제도 고침
  • 설정 오류 알림의 표시 시간은 애니메이션 slowdown/speedup 설정 영향을 받지 않도록 바뀜

IME와 팝업

  • GTK 4 팝업 입력창과 IME가 함께 동작하지 않던 오래된 문제를 우회적으로 해결함
    • Fcitx5 같은 IME를 켠 상태에서는 텍스트 입력 팝업을 열 수 없었음
    • 팝업이 포인터와 키보드 grab을 잡고, IME도 키보드 grab을 쓰기 때문에 충돌이 발생했음
    • niri가 팝업 grab을 버리면서 팝업이 즉시 닫히곤 했음
    • Smithay 구조를 완전히 바꾸지 않고도 동작하도록 일부 검사를 완화함
    • 이제 IME 사용자는 Nautilus에서 파일 이름 바꾸기 같은 작업을 할 수 있음

드래그 앤 드롭과 입력 장치

  • 드래그 앤 드롭 중 Escape를 누르면 작업을 취소할 수 있게 됨
  • 입력 장치 전반에도 여러 수정이 들어감
    • 고주사율 마우스와 hide-after-inactive-ms 또는 idle 모니터링 데몬을 함께 쓸 때 시간이 갈수록 느려지던 문제를 고침
    • libwayland-server v1.23 이상에서는 Wayland 버퍼 크기를 늘려, 반응 없는 창 위에서 고주사율 마우스를 움직일 때 창이 빠르게 크래시 나지 않게 함
    • map-to-focused-output 태블릿 옵션이 추가되어, 지정된 단일 출력 대신 현재 포커스된 출력에 매핑할 수 있음
    • workspace 최상단 픽셀에서 커서가 최대화된 창을 항상 정확히 가리키지 않던 문제를 고침
    • Alt-Tab이 화면에 보이기 전 마우스 입력에 반응하던 문제를 고침
    • trackball의 on-button-down 스크롤이 overview에서도 동작함
    • 커스텀 .xkb keymap 로드 후에도 Num Lock 상태를 유지함
    • tmux를 통해 다른 TTY에서 시작할 때 입력 장치를 전혀 못 쓰던 문제를 고침
    • libinput plugins 로딩을 활성화함

GPU 프로파일링과 렌더링 최적화

  • Smithay와 niri에서 쓰는 TracyGPU 프로파일링 통합이 추가됨
    • GPU 타임스탬프 쿼리를 제출하고, 완료된 값을 수집해 Tracy로 보내는 작업이 Smithay에 들어감: 작업 PR
    • Smithay 내부 GPU 작업과 compositor 자체 GPU 작업 모두 구간 표시가 가능해짐
    • 단일 프레임에서 DRM 버퍼 렌더링과 PipeWire 스크린캐스트 버퍼 렌더링이 어떻게 겹치는지 추적 가능함
    • 멀티 GPU 시스템에서는 GPU별 트랙도 확인 가능함
    • blur 성능이 예상보다 느리지 않음을 검증할 수 있었고, GPU 렌더링 정체로 인한 dropped frame 진단도 쉬워짐
  • 렌더 리스트 구성 방식이 iterator 기반에서 push 기반으로 재구성됨
    • 기존에는 -> impl Iterator<Item = ...> 형태로 렌더 요소를 조합했음
    • 조건 분기, lifetime, &self 대여, &mut Renderer와의 충돌, 중간 Vec 할당, crate 경계 문제 등 여러 복잡성이 있었음
    • 새 구조는 렌더 함수가 push: &mut dyn FnMut(Element)를 받아 요소를 밀어 넣는 방식임
    • 중간 함수는 상위 push를 감싼 클로저로 기존 로직을 유지할 수 있음
    • 임시 Vec가 사라지고 borrowing 문제도 없어짐
    • niri에서는 iterator 조기 종료 이점이 실제로 필요하지 않았음
  • 이 리팩터링으로 렌더 리스트 구성 속도가 크게 빨라짐
    • 주요 머신에서는 2~3배 빨라짐
    • 오래된 Eee PC에서는 8배 빨라짐
    • 렌더 리스트 구성은 실제 GPU 렌더링 시간 자체는 아니지만, 화면을 다시 그리지 않아도 자주 실행되므로 개선 효과가 큼
    • 메모리 사용도 줄어들었고, 새 경로의 할당은 대부분 출력 벡터 확장에만 남음
    • 자세한 동기와 diff는 PR에서 볼 수 있음

구형 하드웨어 지원

  • 오래된 Intel 노트북에서 스크린샷이 실패하던 문제의 원인이 Smithay의 잘못된 OpenGL enum 값으로 밝혀졌고 수정됨: 원인 분석 PR
  • niri 셰이더도 소폭 최적화되어 아주 오래된 ASUS Eee PC의 제한적인 GPU에서도
    • 창 리사이즈 애니메이션
    • compositor 둥근 모서리
    • 동작 가능해짐

기타 개선

  • VRAM 누수가 일부 시스템에서 특정 앱 종료 후 발생하던 문제를 고침
  • ext-foreign-toplevel-list 프로토콜이 추가되어 Quickshell 등에서 Wayland 창 객체와 niri IPC 창 ID를 연결하기 쉬워짐
  • 설정에서 중복 bind 오류가 나면 같은 bind의 첫 정의 위치도 함께 표시함
  • Mod+LMB 창 드래그 시 grabbing cursor를 표시함
  • niri msg action load-config-file에 --path 인자가 추가되어 런타임에 다른 설정 파일로 전환할 수 있음
  • nested niri에 DMA-BUF 지원이 들어가 Mesa의 wl_drm 폐기 이후에도 하드웨어 가속이 다시 동작함
  • 모니터 가장자리 근처 layer-shell 팝업에 niri가 넣던 padding을 제거함
  • 기본 설정 변경도 포함됨
    • Mod+M: maximize-window-to-edges
    • Mod+Shift+R: switch-preset-column-width-back
  • force-disable-connectors-on-resume 디버그 플래그가 추가되어 TTY 전환이나 절전 복귀 시 강제로 화면을 blank 처리할 수 있음
  • windowed fullscreen에서 창 모서리가 올바르게 직각 처리되도록 고침
  • overview가 열린 동안 화면이 계속 다시 그려지던 문제를 고침
  • 인터랙티브 드래그 중 relative-to=workspace-view gradient border 렌더링을 소폭 보정함
  • Important Hotkeys 대화상자의 diaeresis 단축키 렌더링을 다듬음
  • niri msg action의 expel-window-from-column 설명을 실제 동작과 맞게 아래쪽 창을 내보내는 방식으로 수정함
  • 최근 제거된 output을 클라이언트가 쓰려 할 때 발생할 수 있던 여러 panic을 고침
  • clip-to-geometryy_invert 버퍼를 붙이는 클라이언트와 함께 쓰일 때 렌더링이 깨지던 문제를 고침
  • OpenBSD 빌드를 고침
  • nested niri가 자신의 창 app-id를 설정하도록 바뀜
  • 새 GPU가 꽂히면 ignore-drm-device 디버그 설정을 다시 평가해 /dev/dri/by-path/ 심볼릭 링크도 활용할 수 있음

Smithay 업데이트 반영

  • Smithay 업데이트로 여러 기반 개선도 함께 들어감
    • ARM Mac 같은 일부 장치에서 자동 GPU 선택이 개선됨
    • Asahi와 Pinephone은 수동 render-drm-device 설정 없이 바로 동작 가능해짐
    • wl_shimeji 같은 일부 layer-shell 클라이언트 동작이 나아짐
    • 모니터 EDID가 늦게 로드되는 도크 지원이 개선됨
    • 오래된 Intel 시스템에서 스크린샷과 스크린캐스트가 동작함
    • 절전 중 USB-C 도크 분리 시 오래된 output이 남는 문제를 고침
    • 일부 클라이언트에서 zxdg_exporter_v2 panic을 고침
    • 클립보드 프로토콜을 명시적으로 파괴하지 않는 클라이언트의 메모리 누수를 고침
    • GTK 4.23 개발 릴리스에서 발생하기 시작한 text-input content hint, purpose 관련 panic을 고침
    • drag-and-drop, IME text input, multi-GPU와 성능 전반도 개선됨
Read Entire Article