Окно 'группировка'?

Я просто задавался вопросом, там какой-либо способ 'сгруппировать' окна? Я имею в виду, там способ присоединиться к краям двух или больше окон вместе так, чтобы, когда каждый перемещен, другие перемещения с ним, действуя как одно большое окно? Или по крайней мере что-то подобное, куда перемещение одного окна перемещает другой таким же образом? Я выполняю Ubuntu GNOME 15.10 с GNOME 3.18.

3
задан 20 November 2015 в 19:26

1 ответ

Незаконченный ответ; поиск входа

В то время как на первый взгляд это кажется очень хорошо выполнимым, с помощью wmctrl, как всегда, действительность (намного) более сложна, чем теория.

Я смущаюсь отправлять это как ответ, так как это - только экспериментальный, концептуальный ответ, не готовое к использованию решение (все же) из-за некоторых ошибок. Я отправляю его, тем не менее, в надежде получить некоторый вход при решении проблем в текущей версии. Вопрос достаточно интересен, чтобы дальнейшее развитие (IMO) видело, может ли гладкое решение быть создано.

Язык:Ничего

Хотя я записал сценарий в Python, язык не важен проблемам, с которыми я сталкиваюсь; главным образом связанный с особенностями в использовании wmctrl.

Я мог использовать xdotool к окнам положения, но так как OP упоминает движущийся ряд окон другой рабочей области, wmctrl имеет некоторые преимущества, особенно при использовании Gnome, где рабочие области расположены отличающиеся от Единицы.

Пример, как это в настоящее время работает, перемещая группу окон

enter image description here

движущиеся окна как группа

Пример в экранном броске выше был сделан на Единице. Это должно однако работать так же над Gnome (кроме отклонения, посмотрите далее ниже о сценарии).

  • В текущей установке группа окон может быть создана путем добавления frontmost окна к группе путем вызова сценария ниже с аргументом: a. В экранном броске я добавил команду к (Единица) средство запуска, на Gnome, это могло быть сделано с сочетанием клавиш.
  • Впоследствии, если сценарий называют с аргументом r после того, как одно из сгруппированных окон перемещено, сценарий перемещает все окна от группы аналогично, восстанавливая окна, друг относительно друга:

Как это сделано

  • Выполненный с опцией a, сценарий далее ниже добавляет в настоящее время активное окно, его положение и размер (как в соответствующей строке в выводе wmctrl -lG), в файл, wgroup_data.txt~).
  • Выполненный с опцией r, сценарий читает файл, ищет окно, которое сменило положение, вычисляет вектор между старым - и новым положением и перемещает другие окна соответственно.
  • Если окно закрывается, оно автоматически удалено из списка группы сценарием.

До сих пор без проблем.

Проблемы

Однако, если одно из окон не делает полностью пригодный в границах текущей рабочей области, сбоях сценария. На самом деле, wmctrl управляйте сбоями, так как это также перестало работать "вне" скрипта, запущенного как единственная команда.

Сценарий

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

arg = sys.argv[1]

# vertical deviation for Unity (use 0 for Gnome)
deviation = 28

fdata = os.environ["HOME"]+"/wgroup_data.txt"

def get_wmctrl():
    # try because of buggy wmctrl...
    try:
        return subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass

def remove_window(window):
    data = open(fdata).readlines()
    [data.remove(l) for l in data if l.startswith(window)]
    open(fdata, "wt").write(("").join(data))

def addwindow():
    relevant = get_wmctrl()
    frontmost = hex(int((subprocess.check_output(["xdotool", "getactivewindow"]).decode("utf-8").strip())))
    frontmost = frontmost[:2]+str((10-len(frontmost))*"0")+frontmost[2:]
    open(fdata, "+a").write([l+("\n") for l in get_wmctrl().splitlines() if frontmost in l][0])

    print(frontmost)

def rearrange():
    wlist = get_wmctrl()
    if wlist != None:
        group = [(l.strip(), l.split()) for l in open(fdata).read().splitlines() if not l in ("", "\n")]
        try: 
            changed = [w for w in group if (w[0] in wlist, w[1][0] in wlist) == (False, True)][0] #
            # only proceed if one of the grouped windows moved (give priority to a light loop if not):
            follow = []
            for w in group:
                if not w == changed:
                    test = (w[0] in wlist, w[1][0] in wlist)
                    if test == (True, True):
                        follow.append(w)
                    elif test == (False, False):
                        # remove closed window from list
                        remove_window(w[1][0])
            # only proceed if there are windows to move:
            if follow:
                # find match of the moved window (new coords)
                wlines = wlist.splitlines()
                match = [l.split() for l in wlines if changed[1][0] in l][0]
                # calculate the move vector
                x_move = int(match[2])-(int(changed[1][2])); y_move = int(match[3])-(int(changed[1][3]))
                for w in follow:
                    # should be changed to try?
                    w[1][2] = str(int(w[1][2]) + x_move); w[1][3] = str(int(w[1][3]) + y_move - deviation)
                    subprocess.Popen([
                        "wmctrl", "-ir", w[1][0], "-e",
                        (",").join([w[1][1], w[1][2], w[1][3], w[1][4], w[1][5]])
                        ])
                # update grouplist
                while True:
                    try:
                        newlines = sum([[l for l in get_wmctrl().splitlines() if w in l] for w in [match[0]]+[item[1][0] for item in follow]], [])
                        open(fdata, "wt").write(("\n").join(newlines))                 
                        break
                    except AttributeError:
                        pass
        except IndexError:
            print("nothing changed")

if arg == "a":
    addwindow()
elif arg == "r":
    rearrange()

Как использовать

  1. Для сценария нужны оба wmctrl и xdotool

    sudo apt-get install xdotool wmctrl
    
  2. Скопируйте сценарий в пустой файл, сохраните его как group_windows.py

  3. Если Вы находитесь на Gnome:
    В главном разделе сценария измените строку:

    deviation = 28
    

    в

    deviation = 0 
    
  4. Добавьте две команды к различным ярлыкам:

    python3 /path/to/group_windows.py a
    

    добавить окна к группе, и

    python3 /path/to/group_windows.py r
    

    перестроить окна, как показано в экранном броске

  5. Протестируйте сценарий путем добавления некоторых окон к группе, переместите их и восстановите их относительное положение, как показано в экранном броске.

Дальнейшее развитие

Проблема могла быть решена, код - мудрый, просто отказавшись перемещать окна в случае, если любое из окон, как ожидают, выйдет из текущей рабочей области. В этом случае даже справедливое перемещенное окно должно быть возвращено к своему исходному положению для поддержания относительных положений.

Этому однако было бы нужно обширное вычисление (ничто для компьютера, но сложный для кодирования), и это будет более изящно для создания частичного расположения вне текущей рабочей области возможным; это не проблема, когда окно расположено "на или по краю" вручную.
Любые предложения при решении проблемы являются больше, чем приветствие.

1
ответ дан 1 December 2019 в 17:35

Другие вопросы по тегам:

Похожие вопросы: