web-dev-qa-db-ja.com

複数の(2つ以上の)モニター間で半最大化されたウィンドウを移動する

よく使う Ctrl+Super+Arrow -ウィンドウを移動するキー。ただし、マルチモニターがセットアップされている場合、ショートカットは現在の画面上のウィンドウのみを移動します。

**私の状況の例:

3台のモニターがあり、Chromeのインスタンスをセンターモニターで開いています。

  1. 打ったとき Ctrl+Super+Arrow (left)ウィンドウはセンターモニターの左半分に分割されます。
  2. 繰り返しますが、ウィンドウは移動しません。

代わりに見たいのは、[2.]、ウィンドウは左端のモニターの右半分に移動します。

どうすればこの動作を達成できますか?

5
nivla12345

半最大化されたウィンドウを複数の画面に移動します(「エアロスナップ」も同様)

以下のスクリプトは、説明したとおりに機能します。 any画面の数で使用できます。このスクリプトはUnity向けに最適化されていますが、他のウィンドウマネージャーに合わせて簡単に編集できます。

スクリプトはユーザーがランチャーを左端の画面にのみ表示する(または表示しない)ように設定することを考慮に入れる必要があるため、思ったよりもやや複雑になりました。それに応じて、ターゲット位置(およびターゲットウィンドウサイズ)を計算する必要があります。


enter image description here

ノート

  • スクリプトは、ウィンドウをall接続された画面に移動し、続いて画面の「半分」を左から右に、またはその逆に切り替えます。
  • スクリプトは画面のサイズを読み取り、それに応じて画面サイズの半分にウィンドウサイズを設定します。
  • スクリプトはランチャーの設定を読み取り(ランチャーが最初の画面のみに表示される場合、またはすべての画面に表示される場合)、それに応じてターゲットウィンドウサイズを計算します。
  • スクリプトはnotを実行します。これは、ランチャーに設定されている可能性のある自動非表示オプションを考慮します。その理由は、ランチャーが非表示または表示されたときにウィンドウサイズを更新すると、バックグラウンドスクリプトが必要になり、コード作成にはまったく別の話が必要になるからです。
  • ウィンドウは、xdotoolwmctrl-コマンドの組み合わせによって移動およびサイズ変更されます。これらのコマンドは、Unityと組み合わせていくつかの「特徴的な動作」を持つことができるため、ご使用のシステムで小さな変更が役立つ可能性があります。ただし、2つの(まったく異なる)システムでテストし、両方で正常に動作しました。

スクリプト

#!/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
    

    ウィンドウが画面を左に移動するはずです。

  • すべてが正常に機能する場合、両方のコマンドをショートカットキーに追加します。[システム設定]> [キーボード]> [ショートカット]> [カスタムショートカット]を選択します。 [+]をクリックして、選択した2つのショートカットキーにコマンドを追加します。

重要な注意事項

  1. ランチャーwidth65px(アイコンサイズ48px + 17px bordersに対応、デフォルト)に設定されます。設定された幅が異なる場合は、セクションに示されているように、スクリプトのヘッドで正しく設定する必要があります。

    # --- set set launcher width below (default = 65)
    default_launcherwidth = 65
    # ---
    
  2. スクリプトのヘッドセクションには、さらに次の行があります。

    marge = 0
    

    空のマージを設定します右側移動した画面の。必要に応じて別の値に変更します。

3
Jacob Vlijm