在多个(2个或更多)监视器上移动半最大化窗口

我经常使用Ctrl + Super + Arrow -Keys移动窗口。 但是,设置多个监视器后,快捷方式仅移动当前屏幕上的窗口。

**我的情况示例:

我有3个显示器,我的中心显示器中有一个Chrome打开的实例。

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

我想看到的是,在[2.] ,窗口移动到最左侧监视器的右半部分,依此类推

我该如何实现这种行为?

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

下面的脚本与您描述的完全相同。 它可以在任意数量的屏幕上使用。 该脚本针对Unity进行了优化,但可以轻松编辑以适应其他窗口管理器。

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

在此处输入图像描述

笔记

  • 脚本将窗口移动到所有连接的屏幕,随后从左到右切换屏幕的“一半”,反之亦然。
  • 该脚本读取屏幕的大小并将窗口大小设置为相应屏幕大小的一半。
  • 该脚本读取启动器上的设置(如果启动器仅显示在第一个屏幕上或全部显示),并相应地计算目标窗口大小。
  • 该脚本没有考虑启动器可能设置的自动隐藏选项。 原因是,一旦启动器隐藏或显示,更新窗口大小将采用后台脚本,而另一个故事要编写代码。
  • 通过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) 

如何使用

  • scrpt需要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 

    这会在移动的屏幕右侧设置空的marge。 如果您喜欢其他值,请更改它。