멀티플레이어 Wayland: Linux에서 다중 마우스 커서 구현

Wayland는 기본적으로 다중 논리 시트를 지원하여 여러 사람이 하나의 컴퓨터를 사용하고 독립적인 마우스 커서와 키보드 포커스를 가진 동일한 데스크톱 환경을 공유할 수 있게 합니다. 이 “멀티플레이어” 컴퓨팅 모델은 페어 프로그래밍, 게임, 공동 애플리케이션 사용을 위한 실시간 협업을 가능하게 하며, CRDT와 같은 복잡한 동기화 알고리즘을 필요로 하지 않습니다.

Wayland 멀티-시트 아키텍처

멀티-시트 지원은 네 개의 별도 소프트웨어 스택 레이어에 걸쳐 통합되어야 합니다. 어느 레이어라도 지원이 부족하면 다중 커서 기능이 실패합니다.

  1. The Wayland Protocol: 핵심 wayland 프로토콜은 멀티-시트 지원을 깊이 통합하고 있습니다. 모든 입력 이벤트는 wl_pointer 또는 wl_keyboard와 연결되며, 이들은 다시 wl_seat에 연결됩니다. 이를 통해 시스템은 시트별로 입력 이벤트를 그룹화하고 시트가 추가되거나 제거될 때 이벤트를 트리거할 수 있습니다.
  2. The Wayland Compositor: 컴포지터(윈도우 매니저)는 프로토콜을 구현하여 다중 커서를 관리하고 시트별 윈도우 포커스를 처리해야 합니다.
  3. The GUI Library: GTK 또는 SDL과 같은 라이브러리는 이벤트가 어느 시트에서 발생했는지 식별할 수 있어야 합니다.
  4. The Application: 최종 프로그램은 다중 동시 입력 스트림을 처리하도록 작성되어야 합니다.

컴포지터 지원 및 구성

다양한 Wayland 컴포지터는 멀티-시트 기능 구현에 있어 크게 차이가 있습니다.

Sway

Sway는 멀티-시트 지원이 뛰어나며, 시트별 윈도우 포커스를 포함합니다. 사용자는 런타임에 swaymsg seat <name> assign <input_identifier> 명령을 사용하여 입력 장치를 시트에 할당할 수 있습니다. 그러나 현재 제한 사항으로, 장치를 새로운 시트에 할당하면 기존 할당을 교체하지 않고 추가하게 되어 하나의 마우스가 여러 커서를 제어할 수 있습니다 (Sway issue #3491).

Weston

Weston은 레퍼런스 구현으로, 다중 커서와 시트별 윈도우 포커스를 지원합니다. 구성은 Sway보다 복잡하며, 특정 입력 장치에 대해 ENV{WL_SEAT} 속성을 설정하기 위해 udev 규칙을 사용해야 합니다. 예를 들어, /run/udev/rules.d/00-multiseat.rulesATTRS{name}=="Name of your mouse" ENV{WL_SEAT}="second"와 같은 규칙을 추가하여 장치를 시트별로 분리해야 합니다.

River and Niri

River는 전용 river-input-management-v1 프로토콜을 사용해 시트를 생성 및 파괴하는 비단일(monolithic) 접근 방식을 제공합니다. Niri는 현재 공식적인 멀티-시트 지원이 없지만, 최대 두 개의 시트를 지원하는 실험적 포크가 존재합니다.

그래픽 라이브러리 호환성

GTK

GTK4(및 GTK3)는 이벤트의 get_seat 메서드를 통해 멀티-시트를 개념적으로 지원합니다. 그러나 대부분의 표준 GTK 위젯은 멀티-시트 입력을 인식하지 못하고 모든 입력을 단일 장치로 처리합니다. 또한, GTK는 프로그램 실행 중에 새로운 시트가 추가될 때 애플리케이션에 알리지 못합니다 (GTK work item #8327).

SDL

SDL 3(v3.3.4+)는 SDL_VIDEODRIVER 환경 변수를 wayland로 설정하면 멀티-시트 기능을 지원합니다. 이벤트에는 시트를 식별하는 which 필드가 포함됩니다. 알려진 제한 사항으로, 절대 마우스 모드에서는 which 필드가 0으로 강제되며, 실제 장치 ID를 받으려면 SDL_SetWindowRelativeMouseMode를 통해 상대 모드를 활성화해야 합니다 (SDL issue #16027).

wayvnc를 통한 원격 협업

wayvnc(v0.8.0+)를 사용하면 원격 다중 커서 협업이 가능하며, 이는 ext-transient-seat-v1 프로토콜을 구현합니다. --transient-seat 플래그를 사용하면 wayvnc는 들어오는 각 연결마다 새로운 가상 시트를 생성하여 각 원격 사용자에게 자체 마우스와 키보드를 제공합니다.

모든 사용자가 서로의 움직임을 볼 수 있도록 --render-cursor 플래그를 사용해 커서를 출력 스트림에 오버레이로 렌더링하는 것이 권장됩니다. 최적의 성능을 위해 --gpu 플래그를 사용하면 VA-API를 통한 H.264 인코딩이 활성화됩니다.

기술적 과제 및 제한 사항

멀티-시트 지원을 구현하면 UI 및 아키텍처 측면에서 상당한 도전 과제가 발생합니다:

  • Window Focus Assumptions: 많은 GUI 툴킷은 한 번에 하나의 윈도우만 활성화될 수 있다고 가정합니다. 커뮤니티 기여자들이 지적한 바와 같이, gtk_application_get_active_window 또는 QApplication::activeWindow와 같은 함수는 여러 시트가 동시에 서로 다른 윈도우에 포커스를 맞출 때 작동하지 않습니다.
  • Input Conflict: 한 시트가 윈도우를 크기 조정하거나 이동하려고 할 때 다른 시트가 해당 윈도우와 상호작용하고 있으면 경계 상황이 발생합니다. 일부 컴포지터에서는 한 시트가 윈도우를 끄는 동안 다른 시트가 끌고 있으면 두 번째 커서가 사라질 수 있습니다.
  • Application Logic: 대부분의 최종 사용자 애플리케이션은 다중 커서 입력을 위해 설계되지 않았습니다. 예를 들어, Kitty 터미널은 첫 번째 시트를 제외한 모든 시트의 입력을 무시하고, Alacritty는 모든 시트의 입력을 받지만 시트별 컨텍스트는 제공하지 않습니다.

"컨트롤의 포커스가 가장 어려운 부분입니다. 애플리케이션에서 시트별 포커스 버전이 필요하게 됩니다."

Sources