マルチプレイヤー Wayland: Linux で複数のマウスカーソルを実装する

Wayland はネイティブに複数の論理シートをサポートしており、複数の人が単一のコンピュータを使用し、独立したマウスカーソルとキーボードフォーカスを持つ同じデスクトップ環境を共有できます。この「マルチプレイヤー」コンピューティングモデルは、ペアプログラミング、ゲーム、共同アプリケーション利用などのリアルタイム協働を、CRDT のような複雑な同期アルゴリズムを必要とせずに実現します。

Wayland のマルチシートアーキテクチャ

Wayland におけるマルチシートサポートは、ソフトウェアスタックの4つの異なる層の統合が必要です。いずれかの層がサポートされていない場合、マルチカーソル機能は失敗します。

  1. Wayland プロトコル: コアの wayland プロトコルはマルチシートサポートが深く統合されています。すべての入力イベントは wl_pointer または wl_keyboard に紐付けられ、これらはさらに wl_seat に接続されます。これにより、システムはシートごとに入力イベントをグループ化し、シートが追加または削除されたときにイベントをトリガーできます。
  2. Wayland コンポジタ: コンポジタ(ウィンドウマネージャ)は、プロトコルを実装して複数のカーソルを管理し、シートごとのウィンドウフォーカスを処理する必要があります。
  3. GUI ライブラリ: GTK や SDL などのライブラリは、イベントがどのシートから来たかを識別できなければなりません。
  4. アプリケーション: 最終的なプログラムは、複数の同時入力ストリームを処理できるように記述する必要があります。

コンポジタのサポートと設定

Wayland のコンポジタは、マルチシート機能の実装において大きく異なります。

Sway

Sway は、シートごとのウィンドウフォーカスを含む優れたマルチシートサポートを提供します。ユーザーはコマンド swaymsg seat <name> assign <input_identifier> を使用して、実行時に入力デバイスをシートに割り当てることができます。ただし、現在の制限として、デバイスを新しいシートに割り当てると既存の割り当てが置き換えられずに追加されるため、1 つのマウスが複数のカーソルを制御する可能性があります(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 と Niri

River は、シートの作成と破棄のための専用 river-input-management-v1 プロトコルを備えた非モノリシックなアプローチを提供します。Niri は現在公式のマルチシートサポートがなく、実験的なフォークが最大 2 シートをサポートしています。

グラフィックライブラリの互換性

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 とアーキテクチャに大きな課題をもたらします:

  • ウィンドウフォーカスの前提: 多くの GUI ツールキットは同時にアクティブになるウィンドウは1つだけと仮定しています。コミュニティの貢献者が指摘するように、gtk_application_get_active_windowQApplication::activeWindow といった関数は、複数のシートが同時に異なるウィンドウにフォーカスを当てると動作しなくなります。
  • 入力競合: あるシートがウィンドウのサイズ変更や移動を試みている間に、別のシートがそのウィンドウと操作しているといったエッジケースが発生します。一部のコンポジタでは、別のシートがウィンドウをドラッグ中にそのウィンドウを閉じると、2 番目のカーソルが消えてしまうことがあります。
  • アプリケーションロジック: 多くのエンドユーザー向けアプリケーションはマルチカーソル入力を想定していません。例えば、Kitty ターミナルは最初のシート以外からの入力を無視し、Alacritty はすべてのシートからの入力を受け付けますが、シートごとのコンテキストは提供しません。

"コントロールのフォーカスが難しい部分です。アプリケーション内でシートごとのフォーカスが必要になります。"

Sources