マウスボタンコードで使用するときにxbindkeysがマウスクリックを無視するのを防ぐ

マウスボタンコードで使用するときにxbindkeysがマウスクリックを無視するのを防ぐ

Acmeテキストエディタに触発され、マウスボタンコードを設定しようとしています。http://acme.cat-v.org/mouse

Windows と Mac では、それぞれ AutoHotKey と Hammerspoon を使って以下を設定できました。

Left+Middle   = Cut   (Ctrl+x)
Left+Right    = Paste (Ctrl+v)
Middle+Left   = Return
Middle+Right  = Space
Right+Left    = Undo  (Ctrl+z)
Right+Middle  = Redo  (Ctrl+Y / Ctrl+Shift+z)

Middle+Scroll = Switch window

プライマリコンピュータをWindowsからLinuxに移行した後、Linuxでも同じ設定を試しました。私はX11とXFCEを使用してOpenSUSE Tumbleweedを実行しています。

Left+Middle = Ctrl+x簡単にするために、次のコード例ではcut()にのみ焦点を当てます。


を使用してxevマウスの左ボタンを押すと、変数がstateに設定されていることがわかりました0x100

したがって、カットの簡単な構成は次のとおりです。

"xdotool key ctrl+x"
    m:0x100 + b:2

これはうまくいかず、悪名高い衝突プログラムの警告が表示されます。

*** Warning ***
Please verify that there is not another program running
which captures one of the keys captured by xbindkeys.
It seems that there is a conflict, and xbindkeys can't
grab all the keys defined in its configuration file.

m:0x4 + b:2動作するので(0x4はCtrl)問題が何なのかよく分からない。

動作させる方法はありますか?


周囲を検索しながら、自分のニーズに合わせて調整できるマウスコードのいくつかの設定を見つけました。ただし、これにはxbindkeysでチートサポートが必要です。

.xbindkeysrc.scm

(define actionperformed 0)

(define (first-binding)
"First binding"
  (xbindkey-function '("b:1") b1-second-binding) ;; Left Mouse Button
)

(define (reset-first-binding)
"Reset first binding"
  (ungrab-all-keys)
  (remove-all-keys)
  (set! actionperformed 0)
  (first-binding)
  (grab-all-keys)
)


(define (b1-second-binding)
"Left Mouse Button"
  (remove-all-keys)
  (ungrab-all-keys)

  (run-command "xdotool mousedown 1 &") ;; <--- THIS DOES NOT WORK! 

  ;; Left+Middle
  (xbindkey-function '("b:2")
    (lambda ()
      ;; Copy
      (run-command "xdotool key ctrl+x&")
      (run-command "xdotool mouseup 1&")
      (set! actionperformed 1)
    )
  )

  ;; Release left
  (xbindkey-function '(release "b:1") 
    (lambda ()
      (unless actionperformed (begin
        (run-command "xdotool mouseup 1&"))) 
      (reset-first-binding)
    )
  )
  (grab-all-keys)
)

(first-binding)

これにより、Left + Middleがカット操作を実行します。

問題は、左クリックが隠されているため、単純な左クリックやテキストの選択ができないことです。

修正を追加しましたが、xdotool mousedown 1機能しません。

xdotool同じマウスイベントがアクティブな場合、マウスイベントを実行できないようです。

xbindkeysがボタンの正常な動作をオーバーライドするのを防ぐ方法はありますか?


少なくともいくつかの設定を行うためのボタン9を持つ別のマウスがあります。

すべてのボタンコードは同じボタンで始まる必要があるため、実際には3つのコード(+スクロール)しか取得できません。これは私が望むものの半分です。

ボタンを押すのもぎこちなく、永久的な解決策だと見るのは難しいです。

(define (first-binding)
  (xbindkey-function '("b:9") second-binding)
)

(define (second-binding)
  (remove-all-keys)
  (ungrab-all-keys)

  (xbindkey-function '("b:2") (lambda () (run-command "xdotool key ctrl+x")))

  (xbindkey-function '(Release "b:9") reset-first-binding)
)

(define (reset-first-binding)
  (ungrab-all-keys)
  (remove-all-keys)
  (first-binding)
  (grab-all-keys)
)

(first-binding)

この問題を解決する方法についてのアイデアはありますか?

答え1

ついに解決しましたが、回避策は少し複雑です(とにかくWindowsとMacのバージョンと比較して)。

アイデアは、xinputUSBマウスのマウスボタンを再マップしてボタンを無効にしますが、マウスの動きは維持することです。

その後、マウスボタンイベントを受け取り、evtest検出されたボタンの組み合わせに対してマウスコードコマンドをトリガーするか、組み合わせが検出されない場合は通常のボタンイベントをトリガーします。

  1. 設置xinputevtest
  2. evtestUSBマウスを起動して記録してみてください(類似/dev/input/event3
  3. 実行しxinput -listてデバイスIDを書き留めます。
  4. 実行xinput set-button-map {id} 0 0 0 0 0 0 0 0 0 0(0 10個)
  5. 走るevtest /dev/input/event3 | ./mouse-chording.pl

コンテンツmouse-chording.pl:

#!/usr/bin/perl -wlnF/\s|,/

BEGIN
{
    our %btns         = (272 => 0, 273 => 0, 274 => 0);
    our $active_chord = 0;

    # mouse button codes
    our $left_code   = 272;
    our $right_code  = 273;
    our $middle_code = 274;
    our $scroll_code = 8;
}

# only handle events
next unless  0 == index $_, 'Event';
next unless -1 == index $_, 'SYN';

# extract event values
my ($time, $type, $code, $value) = @F[2, 5, 9, 13];

# skip mouse movements and hi-res scroll
next if $code == 11;
next if $type == 2 && $code != 8;

# keep track of pressed buttons
$btns{$code} = $value;

# emulate button presses
if ( ($code == $left_code   && !($btns{$right_code} || $btns{$middle_code}))
  || ($code == $right_code  && !($btns{$left_code}  || $btns{$middle_code}))
  || ($code == $middle_code && !($btns{$left_code}  || $btns{$right_code})) )
{
    if ($code == $left_code)
    {
        # left button can be held for selecting text
        system $value ? "xdotool mousedown 1&" : "xdotool mouseup 1&";
    }
    elsif($value == 0 && not $active_chord)
    {
        # middle and right will only trigger click - cannot be held
        system "xdotool click " . ($code == $middle_code ? 2 : 3) . "&";
    }

    $active_chord = 0;
    next;
}
# emulate scroll wheel
elsif ($code == 8)
{
    system( sprintf("xdotool click %d&", $value > 0 ? 4 : 5) );
}

# only do chords when button is pressed (not released)
next unless $value;

# Left + Middle = Cut
if ($btns{$left_code} && $code == $middle_code)
{
    system "xdotool mouseup 1&"; # prevent accidental selection after snarf
    system "xdotool key ctrl+c key ctrl+x&";
    $active_chord = 1;
    next;
}

# Left + Right = Paste
if ($btns{$left_code} && $code == $right_code)
{
    system "xdotool key ctrl+v&";
    $active_chord = 1;
    next;
}

END
{
    # release buttons to prevent getting stuck when closing
    system "xdotool mouseup $_&" for (1..3);
}

このソリューションは、githubのWindowsとMacのバージョンで維持されています。https://github.com/levigutt/mouse-chording/

PRを歓迎します! :)

関連情報