Ubuntu 14.10 Aero snap в двух горизонтальной установке экрана?

Мне удалось настроить Aero snap влево и вправо, работая в metacity Ubuntu 14.10, и теперь я хотел бы найти правильный winctrl команды, чтобы я мог имитировать тот же эффект на двух экранах, где два экрана расположены горизонтально рядом друг с другом, как на рисунке ниже. Я хочу, чтобы это работало в Metacity (классика GNOME), я вообще не хочу переходить на другие оконные менеджеры, поскольку знаю, что некоторые из них уже имеют эти встроенные возможности. Так что это вопрос, чтобы попытаться найти ответ для классической среды Metacity GNOME:

введите описание изображения здесь

То, что я хочу, это расширить мой текущий winctrl команды. В настоящее время они работают, используя половину общей ширины экрана слева или справа от общей длины экрана. Typing Super_L+left заставит активное окно использовать левую половину, и набрав Super_L+right заставит активное окно использовать правую половину размера всех горизонтальных пикселей.

[hpenvy15 ~] $ cat > ~/bin/left.sh
#!/bin/bash
sleep 0.1 && wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -e 0,0,0,`xwininfo -root | grep Width | awk '{ print (($2/2))}'`,`xwininfo -root | grep Height | awk '{ print $2 }'`
^C
[hpenvy15 ~] $ cat > ~/bin/right.sh
#!/bin/bash
sleep 0.1 && wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -e 0,`xwininfo -root | grep Width | awk '{ print (($2/2)+5) ",0," (($2/2)) }'`,`xwininfo -root | grep Height | awk '{ print $2 }'`
^C

В новой установке с двумя экранами у меня ширина 1920+1920 пикселей. Идеальная ширина окна - половина 1920 года, это 1920/2=960. Хотелось бы по новой left а также right Команды для расчета, где находится окно, в настоящее время, если left набирается, чтобы перейти к ближайшему блоку пикселей шириной 960, в любом из 4 блоков, присутствующих в конфигурации с двумя экранами, 1920+1920, но также работает с ближайшим блоком шириной 960 в конфигурации одного экрана 1920. Диаграмма показана ниже:

Это конфигурация, когда у меня внешний экран в 1 и 2, а экран ноутбука в 3 и 4. В настоящее время, нажав Super_L+leftпереместит окно в левую половину экрана TotalWidth/2, которая будет слишком большой, и перейдет к 1+2.

Я бы хотел первый left команда, чтобы переместить его на панель 3, затем следующий left команда, чтобы переместить его в 2, затем следующий, чтобы переместить его в 1.

   +-------------------++-------------------++-------------------++-------------------+
   |                   ||                   ||                   || +------------+    |
   |                   ||                   ||                   || |            |    |
   |                   ||                   ||           <-------++-+            |    |
   |                   ||                   ||                   || |            |    |
   |         1         ||         2         ||         3         || |       4    |    |
   |                   ||                   ||                   || |            |    |
   |                   ||                   ||                   || +------------+    |
   |                   ||                   ||                   ||                   |
   |                   ||                   ||                   ||                   |
   +-------------------++-------------------++-------------------++-------------------+

Это конфигурация, когда у меня только экран ноутбука в две половины шириной 960 пикселей.

В настоящее время, нажав Super_L+right переместит окно в правую половину экрана TotalWidth/2, что соответствует числу 4.

   +-------------------++-------------------+
   | +------------+    ||                   |
   | |            |    ||                   |
   | |            |    ||                   |
   | |            |----++--->               |
   | |       3    |    ||         4         |
   | |            |    ||                   |
   | |            |    ||                   |
   | +------------+    ||                   |
   |                   ||                   |
   +-------------------++-------------------+

Это вывод wmctrl когда два экрана включены:

wmctrl -d
0  * DG: 3840x1080  VP: 0,0  WA: 0,0 3840x1080  Workspace 1
1  - DG: 3840x1080  VP: N/A  WA: 0,0 3840x1080  Workspace 2
2  - DG: 3840x1080  VP: N/A  WA: 0,0 3840x1080  Workspace 3
3  - DG: 3840x1080  VP: N/A  WA: 0,0 3840x1080  Workspace 4

И это вывод xrandr также когда два экрана включены:

[hpenvy15 ~] $ xrandr
Screen 0: minimum 8 x 8, current 3840 x 1080, maximum 32767 x 32767
eDP1 connected primary 1920x1080+1920+0 (normal left inverted right x axis y axis) 344mm x 193mm
   1920x1080      60.1*+   59.9     40.0  
   1680x1050      60.0     59.9  
   1600x1024      60.2  
   1400x1050      60.0  
   1280x1024      60.0  
   1440x900       59.9  
   1280x960       60.0  
   1360x768       59.8     60.0  
   1152x864       60.0  
   1024x768       60.0  
   800x600        60.3     56.2  
   640x480        59.9  
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 521mm x 293mm
   1920x1080      60.0*+   50.0     59.9     30.0     25.0     24.0     30.0     24.0  
   1920x1080i     60.1     50.0     60.0  
   1680x1050      59.9  
   1600x900       60.0  
   1280x1024      75.0     60.0  
   1440x900       59.9  
   1366x768       59.8  
   1280x800       59.9  
   1152x864       75.0  
   1280x720       60.0     50.0     59.9  
   1440x576i      50.1  
   1024x768       75.1     70.1     60.0  
   1440x480i      60.1     60.1  
   832x624        74.6  
   800x600        72.2     75.0     60.3  
   720x576        50.0  
   720x480        60.0     59.9  
   640x480        75.0     72.8     66.7     60.0     59.9  
   720x400        70.1  
VIRTUAL1 disconnected (normal left inverted right x axis y axis)

1 ответ

Решение

Я тестировал приведенный ниже скрипт на Ubuntu (Gnome) Classic и Gnome Flashback (Metacity) 14.04. "Смешанное" применение xdotool а также wmctrl было необходимо из-за некоторых особенностей, с которыми я столкнулся при написании сценария для Metacity.

Решение

В результате того, что я хотел, чтобы скрипт:

  • определить, какой левый / правый экран
  • рассчитать разрешение обоих мониторов
  • также отлично работает, если два экрана имеют разное разрешение (и рассчитывают как положения, так и целевые размеры окон)
  • работает нормально, если подключен второй экран или нет

- сценарий стал немного более обширным, чем я предвидел.

Что оно делает:

Если подключен второй монитор:
Это работает в значительной степени, как вы описываете:

  • он разделяет два экрана на четыре области, каждая из которых имеет половину размера экрана, на котором она расположена (как сказано, также с разными разрешениями)
  • запустив его с опцией "влево" или "вправо":
    • он перемещает окно в область слева / справа от окна
    • изменяет размеры по горизонтали до половины размера целевого экрана
    • максимизирует окно по вертикали

Если второй монитор не подключен:
Работает традиционным способом:

  • запустить с параметром "влево", это максимизирует самое переднее окно по вертикали в левой половине экрана
  • запустить с опцией "вправо", это максимизирует самое переднее окно по вертикали на правой половине экрана

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

  • Установите оба xdotool а также wmctrl:

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
    
  • Скопируйте скрипт в пустой файл, сохраните его как aero.py запустить его по команде

    python3 /path/to/aero.py left
    python3 /path/to/aero.py right
    

Сценарий

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

move = sys.argv[1]

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def execute(cmd):
    subprocess.call(["/bin/bash", "-c", cmd])

# screen resolutions ("raw")  
wds = [s for s in get("xrandr").split() if s.endswith("+0")]
# x-res left/right)
left = [scr.split("x")[0] for scr in wds if scr.endswith("+0+0")]
right = [scr.split("x")[0] for scr in wds if not scr.endswith("+0+0")]
# x-positions areas
left_pos = [0, int(int(left[0])/2), int(left[0])]
right_pos = [int(int(left[0])+int(right[0])/2)] if len(right) != 0 else []
x_positions = left_pos+right_pos
# frontmost window pos
frontmost =get("printf 0x%x "+get("xdotool getwindowfocus").strip())
frontmost = frontmost[:2]+"0"+frontmost[2:]
f_data = [l.split() for l in get("wmctrl -lG").splitlines() if frontmost in l][0][:6]
curr_pos = int(f_data[2])
area = len([x for x in x_positions if x <= curr_pos])
if move == "left":
    i = area-2; target_pos = x_positions[i] if i >= 0 else 0 
elif move == "right":
    i = area; target_pos = x_positions[area] if area < len(x_positions) else x_positions[-1]
if i >= 2:
    perc = int((100*(x_positions[-1]-x_positions[-2])/sum([int(it) for it in left+right])))
else:
    perc = int((100*(x_positions[1]-x_positions[0])/sum([int(it) for it in left+right])))
# execute actions
cmd1 = "wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz"
cmd2 = "wmctrl -ir "+f_data[0]+" -e 0,"+str(target_pos)+","+"30,300,300"
cmd3 = "xdotool windowsize $(xdotool getactivewindow) "+str(perc)+"% 100%"
for cmd in [cmd1, cmd2, cmd3]:
    execute(cmd)

Также опубликовано на gist.gisthub (последняя версия)

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