将半最大化窗口移动到多个(2 个或更多)显示器

将半最大化窗口移动到多个(2 个或更多)显示器

我经常使用Ctrl++键来移动窗口。但是,在设置SuperArrow显示器的情况下,快捷键只会移动当前屏幕上的窗口。

**我的情况示例:

我有 3 个显示器,并且我Chrome的中央显示器上有一个打开的实例。

  1. 当我按下Ctrl+ Super+时Arrow (left),窗口分裂到我的中央显示器的左半部分。
  2. 当我重复时,窗口没有移动。

我希望看到的是[2.],窗口移动到最左侧显示器的右半部分,依此类推

我如何实现这种行为?

答案1

将半最大化的窗口移动到多个屏幕上(类似于“aero-snap”)

下面的脚本完全按照您描述的方式执行。它可以用于任何屏幕数量。该脚本针对 Unity 进行了优化,但可以轻松编辑以适应其他窗口管理器。

事实证明,这比我想象的要复杂一些,因为脚本应该考虑到用户可能将启动器设置为仅出现在最左侧的屏幕上(或不出现)。目标位置(和目标窗口大小)应该据此计算。


在此处输入图片描述

笔记

  • 脚本通过全部连接的屏幕,随后在屏幕的“两半”之间切换,从左到右,反之亦然。
  • 该脚本读取屏幕尺寸并相应地将窗口尺寸设置为屏幕尺寸的一半。
  • 该脚本读取启动器上的设置(如果启动器仅出现在第一个屏幕上或所有屏幕上),并据此计算目标窗口大小。
  • 脚本确实不是考虑可能为启动器设置的自动隐藏选项。原因是启动器隐藏或显示后更新窗口大小需要后台脚本,而编写代码又是另一回事。
  • 窗口通过xdotoolwmctrl- 命令的组合进行移动和调整大小。由于这些命令与 Unity 结合使用时可能会产生一些“特征行为”,因此您的系统上可能存在微小的更改。不过,我在两个(完全不同的)系统上进行了测试,发现它们都运行良好。

剧本

#!/usr/bin/env python3
import subprocess
import sys

# --- set possibly wanted marge (on the right side of the window) below
marge = 0
# --- set set launcher width below (default = 65)
default_launcherwidth = 65
# ---

move = sys.argv[1]
get = lambda cmd: subprocess.check_output(
    ["/bin/bash", "-c", cmd]).decode("utf-8")

screendata = [l for l in get("xrandr").splitlines() if " connected" in l]
# get the primary screen's position
pr = [l.split() for l in screendata if "primary" in l][0]
i = pr.index("primary"); s = pr[i+1]
primary= [int(s.split("x")[0]), int(s.split("+")[-2])]
# general screen list
screendata = [
    [s for s in l.split() if s.count("+") == 2][0] for l in screendata
    ]
screendata = [
    [int(s.split("x")[0]),int(s.split("+")[-2])] for s in screendata
    ]
screendata.sort(key=lambda x: x[1]); primary = screendata.index(primary)

def launcher_size():
    launcherset = get(
        "dconf read /org/compiz/profiles/unity/plugins/unityshell/num-launchers"
        ).strip()
    l_size_0 = 65; l_size_1 = l_size_0 if launcherset == "0" else 0
    return [l_size_0, l_size_1]

def magnets(index):
    l_size = l_sizes[0] if index == primary else l_sizes[1]
    screen = screendata[index]
    screenwidth = screen[0]; shift = screen[1]
    parts = (screenwidth - l_size)/2; virtual_mid = screenwidth - parts + shift
    left_trigger = shift + l_size
    return [left_trigger, int(virtual_mid), int(parts)]

def find_screen(x_loc):
    scr_index = len([scr for scr in screendata if x_loc >= scr[1]])-1
    scr_index = scr_index if scr_index >= 0 else 0
    screen = screendata[scr_index]
    return [scr_index, screen]

def get_active():
    active = hex(int(get("xdotool getactivewindow").strip()))
    active = active[:2]+(10-len(active))*"0"+active[2:] 
    x_pos = int([l.split()[2] for l in get("wmctrl -lG").splitlines() \
                 if l.startswith(active)][0])
    return [active, x_pos]

def decide(x_loc, active):
    current_scr = find_screen(x_loc)
    triggers = magnets(current_scr[0])
    width = triggers[2]
    index = current_scr[0]
    if move == "left":
        if x_loc <= triggers[1]:
            if x_loc == triggers[0]:
                if index != 0:
                    alter = magnets(index-1) 
                    width = alter[-1]
                    target = alter[1]
                else:
                    target = triggers[0]
            else:
                target = triggers[0]
        elif x_loc > triggers[1]:
            target = triggers[1]        
    elif move == "right":
        if x_loc >= triggers[1]:
            if index != len(screendata)-1:
                alter = magnets(index+1)
                width = alter[-1]
                target = alter[0]
            else:
                target = triggers[1]
        elif x_loc < triggers[1]:
            target = triggers[1]
    subprocess.call([
        "wmctrl", "-r", ":ACTIVE:","-b", "remove,maximized_vert,maximized_horz"
        ])
    subprocess.call(["wmctrl", "-ir", active, "-e", "0,"+str(target)+",400,"+\
                      str(int(width)-marge)+",200"])
    subprocess.call([
        "wmctrl", "-ir", active, "-b", "toggle,maximized_vert"
        ])

l_sizes = launcher_size()
w_data = get_active()
active = w_data[0]
x_loc = w_data[1]

decide(x_loc, active)

如何使用

  • 该脚本需要wmctrlxdotool

    sudo apt-get instal xdotool wmctrl
    
  • 将脚本复制到一个空文件中,另存为move_window.py

  • 通过(重复)以下命令从终端窗口测试运行脚本:

    python3 /path/to/move_window.py right
    

    它将把窗口从你的屏幕移动到右边,并且:

    python3 /path/to/move_window.py left
    

    这会将窗口从屏幕左侧移动。

  • 如果一切正常,请将两个命令添加到快捷键中:选择:系统设置 > “键盘” > “快捷键” > “自定义快捷键”。单击“+”并将命令添加到您选择的两个快捷键中。

重要笔记

  1. 启动器宽度设置为65px(对应图标大小48px+17px边框,为默认值)。如果设置的宽度不同,则应在脚本头部正确设置,如本节所示:

    # --- set set launcher width below (default = 65)
    default_launcherwidth = 65
    # ---
    
  2. 在脚本的头部,还有一行:

    marge = 0
    

    设置空白边缘在右边移动屏幕的数值。如果您愿意,可以将其更改为其他值。

相关内容