마우스 버튼 코드에 사용될 때 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.

따라서 cut의 간단한 구성은 다음과 같습니다.

"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을 환영합니다! :)

관련 정보