如何在 bash 中获取 MouseMove 和 MouseClick?

2024-11-01 08:41:00
admin
原创
141
摘要:问题描述:我想知道如何在 Bash 脚本中获取 MouseClick 和 MouseMove 事件用于我自己的简单操作系统事件。请告诉我如何获取该事件。解决方案 1:xterm 终端仿真器定义了一些控制序列来执行鼠标跟踪,您可以在 xterm 发行版的文档ctlseqs中的“鼠标跟踪”部分中了解有关它们的更多...

问题描述:

我想知道如何在 Bash 脚本中获取 MouseClick 和 MouseMove 事件用于我自己的简单操作系统事件。

请告诉我如何获取该事件。


解决方案 1:

xterm 终端仿真器定义了一些控制序列来执行鼠标跟踪,您可以在 xterm 发行版的文档ctlseqs中的“鼠标跟踪”部分中了解有关它们的更多信息。如果您安装了 xterm,您可能会在或类似路径中有一个副本。/usr/share/doc/xterm/ctlseqs.txt.gz

在 X Window 系统上运行的大多数终端仿真器(例如:Konsole、gnome-terminal、eterm 等)至少能理解其中的一些控制序列。如果您想在 Linux 的虚拟终端上直接使用它们,您可能必须运行gpm(8)

有几种用于启用和禁用鼠标移动报告的控制序列:

  • 9 -> X10 鼠标报告,为了与 X10 的 xterm 兼容,报告按钮按下情况。

  • 1000 -> X11 鼠标报告,报告按钮按下和释放。

  • 1001 -> 突出显示报告,对于报告鼠标突出显示有用。

  • 1002 -> 按钮移动报告,按下按钮时报告移动。

  • 1003 -> 所有运动报告,报告所有运动。

控制序列CSI ? number h用于启用和CSI ? number l禁用。CSI 是ESC [或 字符0x9b。因此,您可以按如下方式使用它们:

echo -e "e[?1000h"

然后,按下按钮时您将获得一堆字符,有关详细信息,请参阅ctlseqsconsole_codes(4)。然后,您可以使用以下命令禁用鼠标跟踪:

echo -e "e[?1000l"

不幸的是,以前的鼠标报告模式只能处理最大 223 (255 - 32) 的坐标,或者在某些情况下处理 95 (127 - 32) 的坐标。因此,有一些新的开关可以更改报告鼠标坐标的格式:

  • 1006 -> 以十进制值形式报告(xterm,许多其他终端仿真器,但不是 urxvt)

  • 1015 -> 以十进制值形式报告(urxvt、xterm、其他终端仿真器、某些应用程序发现解析起来很复杂)

  • 1005 -> 报告编码为 utf-8 (xterm, urxvt, 多种方式损坏)

对于应用程序来说,一个好的策略是启用鼠标报告,然后(可选请求 urxvt 1015 模式,然后)请求 SGR 1006 模式。应用程序应该处理新旧鼠标报告响应,以便在不支持新模式的情况下继续在终端仿真器上工作。

有关新报告模式的更多信息,请访问:

  • 午夜指挥官票#2956

  • tmux 票证 #26

  • 午夜指挥官票#2662

解决方案 2:

根据这里提供的宝贵信息,并经过一番挖掘。

我们可以捕捉鼠标按下和释放、滚轮移动和侧移、鼠标中键单击(滚轮单击)和位置。没有右键单击。

以下只是php 中的一个示例,用作 cli。它隐藏了终端上打印的动作,并在退出时将其正确设置回来。

它足够详细,可以适应任何能够读取STDIN并打印到STDOUT的编程语言,所以肯定有一个很大的列表!

#!/usr/bin/php
<?php
system("stty -icanon");                                  // Enable shell input
system("stty -echo");                                    // Disable characters printing
echo "e[?1003he[?1015he[?1006h";                      // Mouse trap all, urxvt, SGR1006  

function shutdown(){                                     // Cleaning before quiting
    echo "e[?1000l";                                    // Disable mouse trap
    system("stty echo");                                 // Enable back characters printing
    exit;                                                // Cleaned, quit
}
register_shutdown_function("shutdown");                  // Handle regular END of script

declare(ticks = 1);                                      // Allow posix signal handling
pcntl_signal(SIGINT,"shutdown");                         // Catch SIGINT (CTRL+C)   

$KEY = "";
while ($KEY = fread(STDIN,16)) {
  $e = explode(";",explode("<",$KEY)[1]);
  if ($e[0] === "0" && substr($e[2],-1) === "M"){
     echo "BUTTON DOWN, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "0" && substr($e[2],-1) === "m"){
     echo "BUTTON UP, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "64"){
     echo "WHEEL SCROLL UP, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "65"){
     echo "WHEEL SCROLL DOWN, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "1" && substr($e[2],-1) === "M"){
     echo "WHEEL BUTTON DOWN, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "1" && substr($e[2],-1) === "m"){
     echo "WHEEL BUTTON UP, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
  if ($e[0] === "35"){
     echo "MOUSE MOVE, LINE ".substr($e[2],0,-1)." COLUMN ".$e[1]."
"; 
  }
}

在此处输入图片描述

解决方案 3:

捷径

  1. 启用 xterm 鼠标跟踪报告

  2. 设置 readline 绑定以使用点击生成的转义序列

路还很长

Xterm 具有鼠标跟踪功能

echo -e "e[?1000;1006;1015h" # Enable tracking
echo -e "e[?1000;1006;1015l" # Disable tracking
  • 鼠标单击看起来像e[<0;3;21M并释放e[<0;3;21m。其中3x 是 ,21y 是,从左上角 1 开始。(请注意,它是 xy 而不是 row-col)。

  • 鼠标向上滚动:e[<64;3;21M

  • 鼠标向下滑动:e[<65;3;21M

  • 启用鼠标跟踪后按Ctrl + v或 Enter 键read即可看到

Readline 可以触发 bash 回调

bind -x '"e[<64;": mouse_void_cb' # Cannot be put in .inputrc
bind    '"C-h"   : "$(date) eC-eefefefefef"' #Can be put in .inputrc

Readline可以调用多个函数

# Mouse cursor to begining-of-line before calling click callback
bind    '"C-98" : beginning-of-line'
bind -x '"C-99" : mouse_0_cb'
bind    '"e[<0;": "C-98C-99"'

Readline 回调可以使用READLINE_POINT环境变量改变光标(点)的位置

bind -x '"C-h"  : xterm_test'
function xterm_test {
    echo "line is $READLINE_LINE and point $READLINE_POINT"
    READLINE_POINT=24    # The cursor position (0 for begining of command)
    READLINE_LINE='coco' # The command line current content
}

链接

  • 用于鼠标跟踪的 bash 脚本:免责声明,我是该脚本的作者

  • 用于鼠标跟踪的 zsh 脚本:相同,但在 zsh 中(不是 bash)

  • Ctrl 键与 vim 源代码中使用的一样

  • Invisible-Island:Xterm 控制序列的参考(vim /usr/share/doc/xterm/ctlseqs.txt.gz

解决方案 4:

bash 对鼠标或鼠标点击一无所知。默认情况下没有光标或类似的东西。

您可以安装“通用鼠标服务器”。例如,查看:http://www.linuxfromscratch.org/blfs/view/6.3/general/gpm.html
,以便在控制台内使用复制和粘贴。也许您可以使用这些工具来处理您的 bash 脚本。

...但根本没有:bash-shell 没有原生的鼠标支持

解决方案 5:

您可以使用包“xautomation”中的命令“xte”。

apt-get install xautomation

例如,可以记下以下命令:

xte 'mousemove 200 300'

因此,鼠标指针移动到屏幕的宽度 200 和高度 300。作为另一个示例,我们有:

xte 'mouseclick 3'

单击鼠标右键(1:单击左键,2:单击中键,3:单击右键)。此外,您还可以通过 shell 按键盘上的键:

xte 'keydown Control_L' 'key c' 'keyup Control_L'

此示例将 ctrl+c 发送到 shell。

解决方案 6:

我希望你能理解GoLang :)

根据这条评论。<3

package main

import (
  &quot;fmt&quot;
  &quot;strings&quot;
  &quot;strconv&quot;

  &quot;github.com/pandasoli/goterm&quot;
)

func main() {
  termios, _ := goterm.SetRawMode()
  defer goterm.RestoreMode(termios)

  fmt.Print(&quot;[?1003h[?1015h[?1006h&quot;) // Mouse trap all, urxvt, SGR1006
  fmt.Print(&quot;[?1002h&quot;) // Enable mouse motion reporting

  defer fmt.Print(&quot;[?1002l&quot;) // Disable mouse trap
  defer fmt.Print(&quot;[?1003l[?1015l[?1006l&quot;) // Restore mouse mode and SGR1006

  for {
    key, _ := goterm.Getch()

    if key == &quot;q&quot; { break }

    if strings.HasPrefix(key, &quot;[&lt;&quot;) {
      list := strings.Split(key[3:], &quot;;&quot;)

      ev := list[0]
      x, _ := strconv.Atoi(list[1])
      y, _ := strconv.Atoi(list[2][:len(list[2]) - 1])
      kind := list[2][len(list[2]) - 1]

      switch ev {
      case &quot;0&quot;:
        if kind == &#039;M&#039; {
          fmt.Printf(&quot;(%d, %d) Left mouse down
&quot;, x, y)
        } else if kind == &#039;m&#039; {
          fmt.Printf(&quot;(%d, %d) Left mouse up
&quot;, x, y)
        }
      case &quot;1&quot;:
        if kind == &#039;M&#039; {
          fmt.Printf(&quot;(%d, %d) Wheel button down
&quot;, x, y)
        } else if kind == &#039;m&#039; {
          fmt.Printf(&quot;(%d, %d) Wheel button up
&quot;, x, y)
        }
      case &quot;2&quot;:
        if kind == &#039;M&#039; {
          fmt.Printf(&quot;(%d, %d) Right mouse down
&quot;, x, y)
        } else if kind == &#039;m&#039; {
          fmt.Printf(&quot;(%d, %d) Right mouse up
&quot;, x, y)
        }
      case &quot;32&quot;:
        if kind == &#039;M&#039; {
          fmt.Printf(&quot;(%d, %d) Left mouse pressed move
&quot;, x, y)
        }
      case &quot;34&quot;:
        if kind == &#039;M&#039; {
          fmt.Printf(&quot;(%d, %d) Right mouse pressed move
&quot;, x, y)
        }
      case &quot;35&quot;:
        fmt.Printf(&quot;(%d, %d) Mouse move
&quot;, x, y)
      case &quot;64&quot;:
        fmt.Printf(&quot;(%d, %d) Wheel scroll up
&quot;, x, y)
      case &quot;65&quot;:
        fmt.Printf(&quot;(%d, %d) Wheel scroll down
&quot;, x, y)
      default:
        code := strings.ReplaceAll(key, &quot;&quot;, &quot;\\033&quot;)
        panic(fmt.Errorf(&quot;Could not understand mouse input: \&quot;%s\&quot;.&quot;, code))
      }
    } else {
      result := key
      codes := [][]string {
        { &quot;&quot;, &quot;\\033&quot; },
        { &quot;&quot;, &quot;\\b&quot; },
        { &quot;
&quot;, &quot;\\n&quot; },
        { &quot;x7f&quot;, &quot;\&quot; },
      }

      for _, code := range codes {
        result = strings.ReplaceAll(result, code[0], code[1])
      }

      fmt.Printf(&quot;Pressed key \&quot;%s\&quot; %v
&quot;, result, []byte(key))
    }
  }
}

解决方案 7:

您可以使用 xdotool 来处理鼠标移动和鼠标单击事件。xdotool 是一个模拟键盘和鼠标的工具。通过输入 sudo apt-get install xdotool 来安装它。通过使用 xdotool,您可以自动执行几乎所有使用键盘和鼠标进行的操作。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用