Я просто задавался вопросом, там какой-либо способ 'сгруппировать' окна? Я имею в виду, там способ присоединиться к краям двух или больше окон вместе так, чтобы, когда каждый перемещен, другие перемещения с ним, действуя как одно большое окно? Или по крайней мере что-то подобное, куда перемещение одного окна перемещает другой таким же образом? Я выполняю Ubuntu GNOME 15.10 с GNOME 3.18.
В то время как на первый взгляд это кажется очень хорошо выполнимым, с помощью wmctrl
, как всегда, действительность (намного) более сложна, чем теория.
Я смущаюсь отправлять это как ответ, так как это - только экспериментальный, концептуальный ответ, не готовое к использованию решение (все же) из-за некоторых ошибок. Я отправляю его, тем не менее, в надежде получить некоторый вход при решении проблем в текущей версии. Вопрос достаточно интересен, чтобы дальнейшее развитие (IMO) видело, может ли гладкое решение быть создано.
Хотя я записал сценарий в Python
, язык не важен проблемам, с которыми я сталкиваюсь; главным образом связанный с особенностями в использовании wmctrl
.
Я мог использовать xdotool
к окнам положения, но так как OP упоминает движущийся ряд окон другой рабочей области, wmctrl
имеет некоторые преимущества, особенно при использовании Gnome, где рабочие области расположены отличающиеся от Единицы.
движущиеся окна как группа
Пример в экранном броске выше был сделан на Единице. Это должно однако работать так же над Gnome
(кроме отклонения, посмотрите далее ниже о сценарии).
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()
Для сценария нужны оба wmctrl
и xdotool
sudo apt-get install xdotool wmctrl
Скопируйте сценарий в пустой файл, сохраните его как group_windows.py
Если Вы находитесь на Gnome:
В главном разделе сценария измените строку:
deviation = 28
в
deviation = 0
Добавьте две команды к различным ярлыкам:
python3 /path/to/group_windows.py a
добавить окна к группе, и
python3 /path/to/group_windows.py r
перестроить окна, как показано в экранном броске
Протестируйте сценарий путем добавления некоторых окон к группе, переместите их и восстановите их относительное положение, как показано в экранном броске.
Проблема могла быть решена, код - мудрый, просто отказавшись перемещать окна в случае, если любое из окон, как ожидают, выйдет из текущей рабочей области. В этом случае даже справедливое перемещенное окно должно быть возвращено к своему исходному положению для поддержания относительных положений.
Этому однако было бы нужно обширное вычисление (ничто для компьютера, но сложный для кодирования), и это будет более изящно для создания частичного расположения вне текущей рабочей области возможным; это не проблема, когда окно расположено "на или по краю" вручную.
Любые предложения при решении проблемы являются больше, чем приветствие.