カーソル
COMPOSITOR.cursor は、デフォルトポインターやSSDのリサイズカーソルなど、
ShojiWMが所有するnamed cursorのXCursorテーマを設定します。
カーソルの移動、
カーソルの形の上書き、
アプリのポインターロックの無視もここで行います。
COMPOSITOR.cursor.configure({
theme: 'Bibata-Modern-Classic',
size: 24,
});
theme にはインストール済みXCursorテーマ名を指定します。size は1から512の
整数で、単位は論理ピクセルです。ShojiWMは出力ごとに適切にスケールされた画像を
選ぶため、24を指定したカーソルはscale 1とscale 2の出力で同じ論理サイズになります。
configure() はShojiWMを再起動せずに反映され、同時に次の処理を行います。
- 後から起動するプロセス向けに
XCURSOR_THEMEとXCURSOR_SIZEを設定する - TTYセッション、または
SHOJI_PUBLISH_ACTIVATION_ENV=1でnestedでの公開を 有効にした場合、これらの変数をsystemdおよびD-Busのactivation environmentへ公開する - ShojiWMがデコードしたカーソル画像とGPUバッファのキャッシュを破棄する
- 次の再描画から新しいnamed cursorを使用する
テーマファイルの再読み込み
テーマ名やサイズを変えずにテーマファイルだけを置き換えた場合は、現在のテーマを 明示的に再読み込みできます。
COMPOSITOR.cursor.reload();
キーバインドから呼び出すこともできます。
COMPOSITOR.key.bind('reload-cursor', 'Super+Shift+C', () => {
COMPOSITOR.cursor.reload();
});
クライアント所有のカーソルサーフェス
Waylandクライアントは独自のカーソルサーフェスを送信できます。この場合、ShojiWMは クライアントから渡されたサーフェスを表示する必要があり、named cursorへ強制的に 置き換えることはできません。
公開したXCursor環境変数により、新しく起動したツールキットは同じテーマを選択できます。 一方、すでに起動しているアプリケーションのクライアント所有カーソルを変更するには、 アプリケーションの再起動や、そのアプリケーション側での設定再読み込みが必要な場合があります。
カーソル設定を変更しても、クライアント所有のカーソルサーフェスは置換・加工されません。
カーソルの移動
setPosition はカーソルを移動します。全体の論理座標か、出力上の点を指定します。
出力上の点は ポインター領域 と同じ
方法で決まります。まず anchor(既定 "center")で置き、offset(x は右、
y は下が正)でずらします。
COMPOSITOR.cursor.setPosition({x: 800, y: 500});
COMPOSITOR.cursor.setPosition({output: 'DP-1', anchor: 'center'});
COMPOSITOR.cursor.setPosition({output: 'DP-1', anchor: 'top-right', offset: {x: -40, y: 40}});
const position = COMPOSITOR.cursor.getPosition();
// { x, y, outputName } — ポインターが一度も動いていない間は undefined
- クライアントには通常の移動として届きます。ホバーやポインターフォーカスは
カーソルに追従し、ポインター領域の
enter/leaveも通知されます。onPointerMoveは発火しません。カーソルを動かすリスナーが自分自身を 呼び続けることはありません。 - どの出力にも入らない点は、最も近い出力に収められます。出力を指定した場合は その出力の中に収まります。
- アプリがポインターをロック・閉じ込めしている間(ゲームなど)、ボタンを 押している間(ドラッグ中)、画面ロック中は無視されます。
getPosition()は直近のポインター移動時点の位置を、コンポジターへ問い合わせずに 返します。どこから呼んでも軽い処理です。
// カーソルを次の出力の中央へ移動
COMPOSITOR.key.bind('cursor-next-output', 'Super+Ctrl+Right', () => {
const outputs = COMPOSITOR.output.list;
const current = COMPOSITOR.cursor.getPosition()?.outputName;
const next = outputs[(outputs.indexOf(current ?? '') + 1) % outputs.length];
if (next) COMPOSITOR.cursor.setPosition({output: next});
});
カーソルを動かせるのはあなたの設定だけです。Wayland のクライアントには カーソルを動かす手段がなく、この API もクライアントには公開されません。
カーソルの形を上書きする
overrideKind(kind) は、ポインターの下のウィンドウの指定に関係なく、指定した名前の
カーソルをどこでも表示します(再度呼ぶまで有効)。"none" でカーソルを隠し、null で
ウィンドウ側の指定に戻します。
COMPOSITOR.cursor.overrideKind('no-drop'); // 「ドロップ不可」カーソルを表示
COMPOSITOR.cursor.overrideKind('none'); // カーソルを隠す
COMPOSITOR.cursor.overrideKind(null); // 元に戻す
名前は CSS の cursor の値("default"、"pointer"、"text"、"grabbing"、"copy"、
"not-allowed"、"ew-resize" など)で、設定中のテーマから探します。ウィンドウ枠の
リサイズカーソルよりも優先されます。
典型的な使い方はドラッグ中のカーソル変更です。 ネスト(ウィンドウ内)実行ではホストがカーソルを描くため、上書きは見た目に反映されません。
アプリのポインターロックを無視する
ゲームなどのアプリは、カーソルをその場に固定したり、ウィンドウ内に閉じ込めたり
できます。その間はカーソルがウィンドウの外へ出られないため、ゲームを終了しないと
Super でゲームのウィンドウをドラッグすることも、別の出力のバーへ行くことも
できません。
bindAppLockIgnoreModifier(modifier) は、modifier を押している間そのロックを
無視します。デフォルト設定では Super を使っています。
COMPOSITOR.cursor.bindAppLockIgnoreModifier('Super');
Super を押すとカーソルが自由になり、押したままゲームのウィンドウをドラッグする
こともできます。ゲームの上で離すとロックが戻ります。
自分で切り替えるときは setAppLockIgnored を使います。
COMPOSITOR.cursor.setAppLockIgnored(true); // アプリのロックを無視
COMPOSITOR.cursor.setAppLockIgnored(false); // 再び従う
ロックを無視している間は次のようになります。
- アプリにはロック解除が通知されます。 多くのゲーム(SDL など)はロックを 保持していて、自分で取り戻します。ブラウザのポインターロックのような1回限りの ロックは、カーソルがウィンドウを出たときと同じく消えるので、ページを クリックし直してください。
- カーソルはアプリが指定した位置に現れます。 アプリはロック解除時のカーソル 位置(照準など)を指定でき、ShojiWM はそれに従います。
- アプリには生のマウス移動が届かなくなります。 カーソルをゲームの上で動かしても、 ゲームの視点は回りません。
- そのアプリの上では、アプリのカーソルの代わりに ShojiWM の既定の矢印を表示します。 ゲームはロック中にカーソルを隠していることが多いため、これでロックが外れていることが 分かります。それ以外の場所では、カーソルはいつもどおりです。
モディファイア自体は、Super + ドラッグのときと同じく、フォーカス中のアプリに
キーとして届きます。