アプリケーションがマウスを離すときにxinput座標変換行列を使用するときのマウスカーソルジャンプを防ぐ方法

アプリケーションがマウスを離すときにxinput座標変換行列を使用するときのマウスカーソルジャンプを防ぐ方法

非常に敏感なマウスがありますが、感度を下げる必要があります。これに対する一般的な解決策は、座標変換行列を許容値に設定するようです。だから、次の値を使用します。

xinput --set-prop 19 'Coordinate Transformation Matrix' 0.25 0 0  0 0.25 0  0 0 1

Minecraftをプレイする際に問題が発生することを最終的に実現したことを除いて、これはうまくいきました。カーソルを返すキーを押すと、マウスを動かすたびにカーソルが画面の左上の象限に移動します。正確な位置は私が使用しているズームの数に比例するので、0.25は0.45よりもカーソルをコーナーに近づけます。また、1より大きい値を使用すると、カーソルはモニターの他の象限に移動します。もちろん、値が 1 の場合、期待どおりにカーソルが画面の中央に残ります。これは最初のマウス入力でのみ発生し、その後は正常に動作します。

このカーソルの移動を防ぐ方法についてのアドバイスが必要です。本当に迷惑ですね。私はこれが厳密にMinecraftの問題だとは思わず、マウスカーソルを取得して解放する他のJavaアプリケーションでもこれが起こると思います。

詳細については、私のコンピュータはKubuntu 18.04とopenJDK 10.0.2を実行しています。

編集:より多くの情報を追加しました。私は通常のワークフロー中に他の場所でもこの動作を見つけ始めました。いつこれが起こったのかはわかりませんが、KDEがマウスイベントとウィンドウフォーカスを処理する方法に関連している可能性があります。私はフォローマウスを使用します - 最初にマウスを使用します。

答え1

私の「解決策」は、中央にあるときにカーソルを所定の位置に保持する変換行列を選択することでした。

使用するマトリックスは次のとおりです。

3 x 3 行列 s 0(1-s)x 0 s(1-s)y 0 0 1

ここで、sは所望のマウス倍率です(例えば、半分の速度の場合は0.5)。 x と y は画面中央の座標です。

x、y値を取得する簡単な方法は、xdotool getmouselocationジャンプする前に使用することです。

はい

私は感度s = 0.4が欲しい。

Minecraftで私の在庫を開くと、xdotool getmouseloationx = 960、y = 1729と報告されます。私のオフセットを計算します(1-s)* x = 0.6 * 960 = 576および(1-s)* y = 0.6 * 1729 = 1037.4

その後、それに応じて座標変換行列を変更しました。

xinput set-prop 8 'Coordinate Transformation Matrix' 0.4 0 576 0 0.4 1037.4 0 0 1

(私のマウスはデバイス8なので、ユーザーのマウスは異なる場合があります。)

欠陥

これは特定の座標の問題のみを解決します。通常、ウィンドウを同じ位置に保持するMinecraftのような場合、この修正はインベントリに入ったときにマウスがジャンプしなくなるのに十分です。

他のユースケースではまだジャンプが発生しますが、マウスが選択したx、yに近づくとジャンプが小さくなります。

数学的詳細

数学の詳細については、次を参照してください。https://math.stackexchange.com/questions/2954781/calculated-the-translation-of-an-affine-matrix-so-that-it-centres-during-scalin

答え2

代わりに加速を使用してください。私のHyperX Pulsefire Surgeの16000 DPIの場合、通常の値は-0.935です。このバグは、自動非表示、マウスの瞬間移動パネルにも適用されます。

答え3

独自のバージョンのXWarpPointerにXIWarpPointerを使用してみてください。それは次のとおりです。

#include <X11/extensions/XInput2.h>
int XWarpPointer(Display *display, Window src_w, Window dest_w, int src_x, int
            src_y, unsigned int src_width, unsigned int src_height, int dest_x, int
            dest_y){
    static int isnew=1;
    static int device=0;
    int dev_temp;
    if(XIGetClientPointer(display,dest_w,&dev_temp)){
        isnew=0;
        device=dev_temp;
    }
    if(isnew) return 1;
    return XIWarpPointer(display,device,src_w,dest_w,src_x,src_y,src_width,src_height,dest_x,dest_y);
}

gcc xwarp.c --shared -o xwarp.so -lXi でコンパイルし、LD_PRELOAD を使用します。

関連情報