有没有办法在连接外部显示器时防止窗户移动?

K0j*_*0j0 9 display multiple-monitors external-monitor

所以,我在我的笔记本电脑上使用 Ubuntu 14.10,偶尔将它插入我的电视以获得第二个屏幕。我的电视在我桌子的左边。当我将其作为笔记本电脑屏幕左侧的外接显示器启用时,笔记本电脑屏幕上的所有窗口都会移动到电视屏幕上。我可以把它们移回去,但每次都必须这样做真的很烦人,尤其是当有几个窗口打开时。

左边的电视

但是,如果我将电视屏幕设置在笔记本电脑屏幕的右侧(实际上),则窗户不会移动。但这是可以理解的使用混乱,因为它与物理设置相反。另外,我不想移动我的桌子。

右边的电视

似乎 Ubuntu 或显示服务器只是假设最左边的显示器是主显示器,并且所有窗口都应该在那里。有没有办法禁用这种行为?

我一直在查看这些论坛,但还没有真正看到任何人发布有关此内容的帖子。我发现的最接近的线程是这个,尽管它不是完全相同的问题。

关闭多个显示器之一时,让 Ubuntu 不移动窗口

谁有想法?如果你这样做,请告诉我。谢谢!

Jac*_*ijm 3

我没有找到一个“秘密”设置来改变看起来设计的行为。看起来确实好像左侧屏幕被假定为“基本”屏幕。

然而,很可能创建一个解决方法,其结果基本相同。您可以创建一个脚本,在连接第二个屏幕时列出所有窗口。随后,最初移动到左侧屏幕的所有窗口都会在一两秒内移回右侧屏幕。所有窗口的大小将被保留。
这就是下面的脚本所做的事情。

两个版本

您可以通过两种方式恢复排列的窗口:

  • 偶尔,第二屏连接后用快捷键运行。
  • 自动在后台运行脚本,等待您的屏幕连接。

如何使用

准备工作

  • 安装wmctrl

    sudo apt-get install wmctrl

  • 借助 查找两个屏幕的名称xrandr,屏幕的名称将位于“已连接”一词之前。

  • 复制以下任一脚本的头部,将这两行中的屏幕名称替换为正确的屏幕名称:

    screen_1 = "LVDS1"     # your main screen (laptop)
    screen_2 = "VGA1"      # secundary screen (on the left)
    
    Run Code Online (Sandbox Code Playgroud)

    将脚本另存为move_windows.py

  • 确保在显示设置中您的辅助屏幕位于左侧。两个屏幕的顶线需要对齐(就像问题的第一张图片中一样)。

运行脚本
- 如果您偶尔使用该脚本,请在连接第二个屏幕后运行它。

    python3 /path/to/move_windows.py
Run Code Online (Sandbox Code Playgroud)

如果您认为它能完成应有的功能,您可能想将其添加到键盘快捷键中,选择:系统设置>“键盘”>“快捷方式”>“自定义快捷方式”。单击“+”并添加命令:

  • 如果使用后台运行,也可以通过以下命令运行:

    python3 /path/to/move_windows.py
    
    Run Code Online (Sandbox Code Playgroud)

    如果它按照您的预期运行,请将其添加到您的启动应用程序中:Dash > 启动应用程序 > 添加

我用我的笔记本电脑(右侧)和两个不同的屏幕(左侧)测试了该脚本。结果是一样的。

笔记本电脑屏幕

在此输入图像描述

无需脚本即可连接

在此输入图像描述

与正在运行的脚本连接

在此输入图像描述

脚本完成其工作后,窗口将“保持独立”(当然),您可以按照自己的方式排列窗口。

脚本

1.“手动”版本,连接屏幕后运行

screen_1 = "LVDS1"     # your main screen (laptop)
screen_2 = "VGA1"      # secundary screen (on the left)
Run Code Online (Sandbox Code Playgroud)

2.自动版本,后台运行

    python3 /path/to/move_windows.py
Run Code Online (Sandbox Code Playgroud)


小智 1

我有多个显示器连接到 HDMI 开关,每当我从一个设备切换到另一个设备时,前一个设备就像显示器已关闭一样。所以我想要为我的笔记本电脑提供类似的东西(我在那里使用两个屏幕)

@JacobVlijm 并不是我想要的东西,但在很大程度上基于此,我制作了一个 bash 脚本,将一些(或全部)窗口从一个屏幕移动到另一个屏幕。特征:

  • 它不关心“左和右”,只关心“从和到”。
  • 可以过滤您要移动的应用程序
  • 是否最好保留窗口大小(最大化时效果完美,非最大化时效果不错)
  • 可以在 bash_aliases 中使用,这样你就不必记住脚本在哪里

要旨

代码

screen_from=${1:-'eDP-1'}
screen_to=${2:-'HDMI-1'}

echo "Moving windows from $screen_from to $screen_to"

apps_to_move=("Firefox" "Gnome-terminal" "Slack" "Sublime_text" "Terminator" "Thunderbird" "Mysql-workbench")

dimensions=`xrandr --listmonitors | grep $screen_to | cut -d ' ' -f4`
width=$(echo $dimensions | cut -f1 -d '/')
height=$(echo $dimensions | cut -f2 -d '/' |cut -f2 -d'x')
offset_x=$(echo $dimensions | cut -f2 -d '+')
offset_y=$(echo $dimensions | cut -f3 -d '+')

dimensions=`xrandr --listmonitors | grep $screen_from | cut -d ' ' -f4`
width_from=$(echo $dimensions | cut -f1 -d '/')
height_from=$(echo $dimensions | cut -f2 -d '/' |cut -f2 -d'x')
offset_x_from=$(echo $dimensions | cut -f2 -d '+')
offset_y_from=$(echo $dimensions | cut -f3 -d '+')

# Parameters: app_name (WM_CLASS or id)
move_window() {
    local app_name=$1

    # Looks for all windows of a given app (only need when WM_CLASS is provided)
    for app in `wmctrl -lGx | grep $app_name | tr -s ' ' | cut -d ' ' -f1`; do
        echo "Processing $app_name - ID: $app"

        cur_offset_x=`wmctrl -lGx | grep $app | tr -s ' ' | cut -d ' ' -f3`

        # Skip if window is already on dest screen
        if [[ $cur_offset_x -lt $offset_x_from ]]; then
            echo "$app is already on desired screen"
            continue
        fi

        echo "Moving $app"
        cur_width=`wmctrl -lGx | grep $app | tr -s ' ' | cut -d ' ' -f5`
        cur_height=`wmctrl -lGx | grep $app | tr -s ' ' | cut -d ' ' -f6`

        # echo "Cur width: $cur_width - Cur height: $cur_height"
        # echo "Width from: $width_from - Height from: $height_from"

        # Needed because otherwise wmctrl doesn't move the window
        wmctrl -ir $app -b remove,maximized_vert,maximized_horz

        # If app is maximized then it should be maximized in dest screen
        # 100 is the threshold to consider "maximized" because taskbars add offsets to windows
        if (( ($width_from - $cur_width < 100) && ($height_from - $cur_height < 100) )); then
            echo "App should be maximized"
            wmctrl -ir $app -e 0,$offset_x,$offset_y,-1,-1
            wmctrl -ir $app -b add,maximized_vert,maximized_horz
        else
            # Instead of keeping the original size I chose to preserve it's ratio in the source screen
            echo "App should preserve it's original size (ratio)"
            new_width=`bc <<< $width*$cur_width/$width_from`
            new_height=`bc <<< $height*$cur_height/$height_from`
            wmctrl -ir $app -e 0,$offset_x,$offset_y,$new_width,$new_height
        fi
    done
}

# If apps_to_move is not empty, use it
if (( ${#apps_to_move[@]} > 0 )); then
    echo "Using apps_to_move"
    for app in "${apps_to_move[@]}"; do
        move_window $app x
    done
# Else, move everything
else
    for app in `wmctrl -l | cut -d ' ' -f 1`; do
        move_window $app i
    done
fi
Run Code Online (Sandbox Code Playgroud)