如何避免鼠标卡在不同尺寸的多个显示器上

如何避免鼠标卡在不同尺寸的多个显示器上

我有两个显示器。一个是 1920x1080(左屏幕),另一个是 1440x900(右屏幕)。

现在,我已将其设置为两个显示器的顶部对齐。这样,当我将鼠标放在左侧屏幕的最顶部并将鼠标向右移动时,它将无缝移动到右侧屏幕。但是,如果我的鼠标位于左侧屏幕的底部 180 像素处,并且我将鼠标向右移动,它不会移动到右侧屏幕,因此我必须先将鼠标向上移动,然后再将其向右移动,因为右侧屏幕比左侧屏幕小。

我想要的功能:如果我在左侧屏幕的底部并将鼠标向右移动,它应该出现在右侧屏幕的底部。

答案1

我遇到了同样的问题,正如其他人指出的那样,Ubuntu 看到你的显示器看起来像这样(也许顺序是相反的):

+----------++----------------+
|          ||                |
|          ||                |
+----------+|                |
            |                |
            +----------------+

在此示例中,当您的鼠标位于底部的右侧显示器中,并且鼠标向左直线移动时,您会遇到无法跨屏幕的死区。我修改了 cassm 发布的 bash 文件,使鼠标高度在跨屏时成比例,因此如果您将鼠标从左侧显示器向上移 3/4,则鼠标会出现在右侧显示器向上的 3/4。

要运行我运行的脚本,请按照以下说明操作:

1)确保在 Ubuntu 的显示设置中,使用脚本中的图片正确设置显示器(上面的一个不同)

2)创建一个名为“mousejumper.sh”或以.sh 结尾的任何文本文件

3)右键单击文件并更改属性以使其可执行

4)将脚本复制并粘贴到文件中

    #! /bin/bash
    # Cursor relocation script by Cass May <[email protected]>

    # LEFTX and RIGHTX are the screen boundaries, which triggers cursor relocation
    # LEFTMONHEIGHT and LEFTMONHEIGHT are the heights in pixels of the left and right monitor
            # minus 1, because computers start counting at 0... so 1920 pixels heigh becomes 1919
    LEFTX="1919"
    LEFTMONHEIGHT="1080"

    RIGHTX="1920"
    RIGHTMONHEIGHT="2159"

    # Size in pixels to jump over the screens with when you hit the boundary (ex: if 5, jumps from x = 1919 to x=1924)
    BUFFER="5"


    # In Ubuntu Displays settings window the two monitors must be setup to look like this:
    #             +----------------+
    #             |                |
    # +----------+|                |
    # |          ||                |
    # |          ||                |
    # +----------++----------------+
    #
    # If the monitor setup is in a different order (ex: larger screen on left side) 
    # or there are more than two monitors, then the script will need to be modified

    # Tip: Set "Sticky Edges" to On in the Displays settings window because 
    # the script checks coordinates every 0.### seconds, and sticky edges
    # keeps your mouse there longer


    while true; do # keep loop going to run all the time, do a slight pause for performance

        # grab cursor position, and extract x and y position
        CURSORPOSITION="$(xdotool getmouselocation)"
        XPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==1{print $1}')"
        YPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==2{print $1}')"
        #echo "Mouse position is: ($XPOS, $YPOS)"


        # if XPOS is 1920 then on right 4k monitor
        if [ $XPOS = $RIGHTX ] 
        then 
            #echo "Starting jump function"
            # find % height then convert
            # Input is 0-2159, Output is 1080-2159
            NEWYPOS=$(echo "(($LEFTMONHEIGHT+$YPOS/$RIGHTMONHEIGHT*$LEFTMONHEIGHT))" | bc -l)
            #echo "YPOS with floats is: $NEWYPOS"
            NEWYPOS=$(echo "$NEWYPOS" | bc -l | xargs printf "%1.0f") 
            NEWXPOS=$(($RIGHTX-$BUFFER))
            # Move Mouse to other screen with a few pixel buffer on the screen edge
            #echo "Mouse jumped from right to left from: ($XPOS, $YPOS) to ($NEWXPOS, $NEWYPOS)"
            xdotool mousemove "$NEWXPOS" "$NEWYPOS"


        # if XPOS is 1919 then on left 1080 monitor
        elif [ $XPOS = $LEFTX ] 
        then 
            #echo "Starting jump function"
            # find % height then convert
            # Input is 0-2159, Output is 1080-2159
            NEWYPOS=$(echo "((($YPOS-$LEFTMONHEIGHT)/$LEFTMONHEIGHT*$RIGHTMONHEIGHT))" | bc -l)
            #echo "YPOS with floats is: $NEWYPOS"
            NEWYPOS=$(echo "$NEWYPOS" | bc -l | xargs printf "%1.0f") 
            NEWXPOS=$(($LEFTX+$BUFFER))
            # Move Mouse to other screen with a few pixel buffer on the screen edge
            #echo "Mouse jumped from left to right from: ($XPOS, $YPOS) to ($NEWXPOS, $NEWYPOS)"
            xdotool mousemove "$NEWXPOS" "$NEWYPOS"

        fi
        sleep 0.05
    done

5)更改脚本中的这些值以匹配您的显示器规格

LEFTX="1919"
LEFTMONHEIGHT="1080"

RIGHTX="1920"
RIGHTMONHEIGHT="2159"

我的显示器左侧是 1920x1080,右侧是 3840x2160。

如果您需要帮助查找监视器的值,请使用这个小型 bash 脚本并移动鼠标:

#! /bin/bash
    while true; do # keep loop going to run all the time, do a slight pause for performance
            # grab cursor position, and extract x and y position
        CURSORPOSITION="$(xdotool getmouselocation)"
        XPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==1{print $1}')"
        YPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==2{print $1}')"
        echo "Mouse position is: ($XPOS, $YPOS)"

        sleep 0.1
done

6)在终端中使用 ./mousejumper.sh 运行

我不想让它一直运行,所以我不会让系统在启动时启动它。我编写了一个小实用程序来手动打开和关闭此类脚本。

答案2

我搞定了一个似乎可以在我的机器上运行的程序。我还没有设法用多个显示器测试它,但我认为这些设置对你有用。它要求你安装 xdotool。

如果有效,请将其放入你的 .rclocal 中,如下所述这里,它将在启动时运行。

#! /bin/bash
# Cursor relocation script by Cass May <[email protected]>

# definitions of "hot zone", which triggers cursor relocation
XZONE="1919"
YZONE="900"

#target for cursor relocation
XTARGET="1920"
YTARGET="899"

while true; do
    # grab cursor position, and extract x and y position
    CURSORPOSITION="$(xdotool getmouselocation)"
    XPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==1{print $1}')"
    YPOS="$(grep -o '[0-9]\+' <<< "$CURSORPOSITION" | awk 'NR==2{print $1}')"

    # perform tests. If you wish to reconfigure this behaviour, and do
    # not know where to start, look up bash numerical comparison operators.
    if [[ "$XPOS" -eq "$XZONE" ]] && [[ "$YPOS" -ge "$YZONE" ]]
    then
        xdotool mousemove "$XTARGET" "$YTARGET"
    fi
    sleep 0.1
done

答案3

发生这种情况的原因在于,您的左显示器高度为 1080 像素,而右显示器高度为 900 像素。由于两者在顶部对齐,因此如果您从右向左移动鼠标,反之亦然,您的鼠标将平稳移动。

但这对于底部边缘不起作用,因为左屏幕的底部比右屏幕的高度高出 180 像素。根据这个问题,这是 X 窗口系统的一个已知错误

如果您使用的是 NVIDIA 硬件和驱动程序,则显示的解决方案可能对您有用,否则您可能会陷入困境。我在使用不同分辨率的双显示器运行 Windows 7 时没有遇到此问题。

答案4

我受@cubash 和 @cassm 的回答启发编写了这个 Python 脚本。它应该比使用 bash 并在每次循环迭代时启动几个新的 xdotool 进程占用更少的资源。

此脚本以给定的 FPS 轮询鼠标位置,并在鼠标“碰到”边缘时将指针扭曲到另一个屏幕。

如果鼠标卡在某个 x 或 y 坐标上,这允许将其传送到给定位置。但是,它不允许对坐标进行平滑插值,将 0..1080p 映射到 0..3840,因为对于屏幕边缘的一半,光标将从一个显示器的区域移动到另一个显示器的区域而不会停在边缘,并且脚本没有时间检测其位置(因为它通过轮询工作)。

您可以扩展它以记录前一个光标的位置,并在前一个位置与当前位置位于不同的显示器上时“缩放”坐标(例如,光标在前一次1900x,540y循环迭代中位于(高清屏幕右边缘中间附近),1950x,540y在当前循环迭代中位于(4K 屏幕左边缘的四分之一左右),因此存在 HD→4K 转换,因此可以将 y 坐标乘以二以将光标放在正确的位置)。

其他替代方案:在显示器之间放置大量空白空间,就像这样xrandr --output DP-1 --pos 0x1080 --auto --output eDP-1 --pos 2920x0,以便脚本有足够的时间在鼠标位于屏幕之间的间隙时抓住它:

                         +------+
                         |      |
+----+                   |  4K  |
| HD | [1000px of space] |      |
+----+                   +------+

其他替代方案:通过使屏幕仅接触一个像素来“撞击”几乎所有地方xrandr --output DP-1 --pos 0x3839 --auto --output eDP-1 --pos 1920x0

      +------+
      |      |
      |  4K  |
      |      |
+----++------+
| HD |
+----+

似乎如果屏幕至少接触一个像素,鼠标就会碰到边缘(这为脚本轮询其位置并传送它提供了时间),但如果屏幕没有接触,则允许鼠标进入未映射到任何屏幕的“边缘”。可能有一种方法可以为鼠标声明“死区”,并阻止它进入这些区域,这将允许光标始终碰到边缘并让脚本检测到它。

#!/usr/bin/env python3
from Xlib import display
from time import sleep
from os import system

# Optional: set the coordinates of the monitors here, I have a 1680x1050 monitor centered on top of a 1920x1080 monitor:
system('xrandr --output DP-1 --pos 120x0 --auto --output eDP-1 --pos 0x1050')

fps=50.0
delay=1.0/fps
d=display.Display()

while True:
  sleep(delay)
  data = d.screen().root.query_pointer()._data
  x = data["root_x"]
  y = data["root_y"]
  # Change conditions and coordinates here, I teleport the two segments on the top left and top right of my 1920x1080 screen to the bottom left and bottom right corners of the 1680x1050 screen:
  if y == 1050 and (x < 120 or x >= 1800):
    if x < 120:
      d.screen().root.warp_pointer(120,1049)
    else:
      d.screen().root.warp_pointer(1799,1049)

相关内容