Как найти окна определенного приложения и поместить их в сетку?

Я пытаюсь написать сценарий, чтобы идентифицировать все открытые окна Chrome и переместить их в макет сетки на большом экране.

Я не уверен, как узнать, какие будут наилучшие разрешения. Я собирался вручную добавить их в массив, чтобы, если было доступно 1 окно Chrome, максимизировать его, если доступно 2 окна Chrome, тогда перейти к массиву для размеров для этого?

В настоящий момент я могу перемещать каждое окно на экране (не нарушает ли мой дисплей при этом), но я вижу, как понять, как перемещать только хромированные экраны?

Сценарий ниже Есть некоторые идеи, которые у меня были, но, пожалуйста, укажите в правильном направлении, так как на данный момент сценарий не работает

#!/bin/bash
#Chrome window crontroller 


# Monitor 1920 X 1800

# Choose array for number of screens available 

# Different screen positions 
G=0
win1_X=5;      win1_Y=24;    win1_W=639;   win1_H=499;
win2_X=642;    win2_Y=24;    win2_W=639;   win2_H=499;
win3_X=1280;   win3_Y=24;    win3_W=639;   win3_H=499;
win4_X=5;      win4_Y=552;   win4_W=639;   win4_H=499;

ChromesAvailable()
{
    CA=$(wmctrl -lx | grep Chromium | wc -l)
}


GetNumOfChrome()
{
  WID=$(wmctrl -l | grep n | awk '{print$1}')
  #echo "INFO: window id = $WID"
}


PlaceWindow()
{
  X=${n}_X; Y=${n}_Y; W=${n}_W; H=${n}_H; 
  wmctrl -i -r "$WID" -e $G,${!X},${!Y},${!W},${!H}
}

if [ "$#" -gt 0 ]; then
 case "$1" in

        *)
            echo "ERROR: invalid option $1"
            echo "see --help for usage"
            exit 1
            ;;
  esac
  exit 0
else
for n in win{1..4}; do
    GetNumOfChrome
    PlaceWindow
done

fi

Отредактировано - Чтобы объяснить вещи лучше: -)

Использование grep n будет загружать каждое открытое окно в системе, поэтому я попытался использовать grep Chromimum, но сценарий не нравится

 GetNumOfChrome()
    {
      WID=$(wmctrl -l | grep n | awk '{print$1}')
      #echo "INFO: window id = $WID"
    }
3
задан 15 May 2015 в 11:50

2 ответа

Другой подход должен расположить форму окон пред - определил (настраиваемую) сетку (столбцы/строки)

Пример:

enter image description here

перестроенный в (cols набор к 3, rows набор к 2):

enter image description here

перестроенный в (cols набор к 4, rows набор к 2):

enter image description here

Сценарий ниже может использоваться, чтобы сделать это. Как сказано, номер columns&rows может быть определен, а также дополнение между окнами. Сценарий вычисляет затем положения, окна должны быть расположены в, а также их размеры.

Используя wmctrl управляют на Единице

wmctrl управляйте показывает некоторые особенности при использовании для перемещения окон в - или очень поблизости средство запуска или панель. Поэтому поля:

left_margin = 70; top_margin = 30

не может быть обнулен. Необходимо сохранить по крайней мере некоторых расстоянием пкс и до панели и до средства запуска. Я предложил бы оставить оба поля - значения как они. Все другие значения, дополнение, столбцы и строки можно играть вокруг с и установить его, как Вам нравится.

Сценарий

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

#--- set your preferences below: columns, rows, padding between windows, margin(s)
cols = 2; rows = 2; padding = 10; left_margin = 70; top_margin = 30
#---

get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_res():
    xr = get("xrandr").split(); pos = xr.index("current")
    return [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]

# get resolution
res = get_res()
# define (calculate) the area to divide
area_h = res[0] - left_margin; area_v = res[1] - top_margin
# create a list of calculated coordinates
x_coords = [int(left_margin+area_h/cols*n) for n in range(cols)]
y_coords = [int(top_margin+area_v/rows*n) for n in range(rows)]
coords = sum([[(cx, cy) for cx in x_coords] for cy in y_coords], [])
# calculate the corresponding window size, given the padding, margins, columns and rows
w_size = [str(int(area_h/cols - padding)), str(int(area_v/rows - padding))]
# find windows of the application, identified by their pid
pids = [p.split()[0] for p in get("ps -e").splitlines() if sys.argv[1] in p]
w_list = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if p in w] for p in pids], [])
print(pids, w_list, coords)
# remove possibly maximization, move the windows
for n, w in enumerate(w_list):
    data = (",").join([str(item) for item in coords[n]])+","+(",").join(w_size)
    cmd1 = "wmctrl -ir "+w+" -b remove,maximized_horz"
    cmd2 = "wmctrl -ir "+w+" -b remove,maximized_vert"
    cmd3 = "wmctrl -ir "+w+" -e 0,"+data
    for cmd in [cmd1, cmd2, cmd3]:
        subprocess.Popen(["/bin/bash", "-c", cmd])

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

  1. Удостовериться wmctrl установлен :)
  2. Скопируйте thye сценарий в пустой файл, сохраните его как rearrange_windows.py
  3. В главном разделе сценария, набор Ваши предпочтения
  4. Выполните его командой:

    python3 /path/to/rearrange_windows.py <application>
    

    пример: перестроить chromium окна:

    python3 /path/to/rearrange_windows.py chromium
    

    перестроить chrome окна

    python3 /path/to/rearrange_windows.py chrome
    

Примечание:

Сценарий может использоваться для помещения окон любого приложения в сетку, так как название процесса приложения используется в качестве аргумента.


Править

Динамическая версия

ниже динамической версии сценария, согласно просьбе в комментарии. Эта версия сценария вычисляет число столбцов и строк, в зависимости от количества окон. Пропорции перестроенного окна (окон) подобны пропорциям экрана.

Установка и использование являются в значительной степени тем же как версией выше, только номер столбцов и строк теперь определяется автоматически.

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

#--- set your preferences below: padding between windows, margin(s)
padding = 10; left_margin = 70; top_margin = 30
#---

get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_res():
    xr = get("xrandr").split(); pos = xr.index("current")
    return [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]

# find windows of the application, identified by their pid
pids = [p.split()[0] for p in get("ps -e").splitlines() if sys.argv[1] in p]
w_list = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if p in w] for p in pids], [])
# calculate the columns/rows, depending on the number of windows
cols = math.ceil(math.sqrt(len(w_list))); rows = cols
# define (calculate) the area to divide
res = get_res()
area_h = res[0] - left_margin; area_v = res[1] - top_margin
# create a list of calculated coordinates
x_coords = [int(left_margin+area_h/cols*n) for n in range(cols)]
y_coords = [int(top_margin+area_v/rows*n) for n in range(rows)]
coords = sum([[(cx, cy) for cx in x_coords] for cy in y_coords], [])
# calculate the corresponding window size, given the padding, margins, columns and rows
if cols != 0:
    w_size = [str(int(area_h/cols - padding)), str(int(area_v/rows - padding))]
# remove possibly maximization, move the windows
for n, w in enumerate(w_list):
    data = (",").join([str(item) for item in coords[n]])+","+(",").join(w_size)
    cmd1 = "wmctrl -ir "+w+" -b remove,maximized_horz"
    cmd2 = "wmctrl -ir "+w+" -b remove,maximized_vert"
    cmd3 = "wmctrl -ir "+w+" -e 0,"+data
    for cmd in [cmd1, cmd2, cmd3]:
        subprocess.call(["/bin/bash", "-c", cmd])

Посмотрите ниже примеров с переменным количеством открытых окон:

enter image description here enter image description here

enter image description here enter image description here

Объяснение (второй сценарий)

Нахождение определенных окон

  1. Команда:

    wmctrl -lp
    

    списки все окна, в формате:

    0x19c00085  0 14838  jacob-System-Product-Name *Niet-opgeslagen document 1 - gedit
    

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

  2. Команда:

    ps -e
    

    списки все процессы, в формате:

    14838 ?        00:00:02 gedit
    

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

  3. Путем сравнения этих двух списков мы можем найти все окна (идентификатор-), которые принадлежат определенному приложению (названный w_list в сценарии, как результат строки 17/18 в сценарии):

    pids = [p.split()[0] for p in get("ps -e").splitlines() if sys.argv[1] in p]
    w_list = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if p in w] for p in pids], [])
    

Вычисление количества строк/столбцы

  1. Если мы делаем окна тех же пропорций как экран, который означает, что количество столбцов равно количеству строк.
  2. Это подразумевает, что и количество colums и строки равны окруженному квадратному корню количества окон для реконструкции. Это сделано в строке 20:

    cols = math.ceil(math.sqrt(len(w_list))); rows = cols
    

Вычисление размера окна и положения

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

    w_size = [str(int(area_h/cols - padding)), str(int(area_v/rows - padding))]
    
  2. Горизонталь (x) положения является результатом продукта (продуктов) горизонтального размера окна (включая дополнение) времена номер столбца в диапазоне числа столбцов. например: если у меня есть 3 colums 300 пкс, получающиеся x-положения:

    [0, 300, 600]
    
  3. Вертикальные (y) положения вычисляются аналогично. Оба списка затем объединены в список координат, в которых будут перестроены окна.

    Это сделано в строке 26-28 из сценария:

    x_coords = [int(left_margin+area_h/cols*n) for n in range(cols)]
    y_coords = [int(top_margin+area_v/rows*n) for n in range(rows)]
    coords = sum([[(cx, cy) for cx in x_coords] for cy in y_coords], [])
    
  4. Фактическая реконструкция наконец (после того, как, не максимизируя возможно максимизируемые окна) сделана от строки 33 и далее.

2
ответ дан 15 May 2015 в 11:50

Сценарий ниже разместит произвольное число рядом окон хрома или хрома в сетке Nx2 (N строки, 2 столбца), где N зависит от количества открытых окон. Если будет только одно окно, то окно будет максимизировано (или не максимизировано, если это будет уже максимизировано).

#!/usr/bin/env bash

#################################################
# Exit if there are no running chrome processes #
#################################################
pgrep "chrom[e|ium]" &>/dev/null || 
    echo "No Chrom[e|ium] processes are running" 1>&2 && exit
#########################
# Get screen dimensions #
#########################
read width x height < <(xrandr | grep -Po 'current\s*\K.*?(?=,)' )

###################################################################
# Get the names of all Chrome windows. I am using PIDs because    #
# searching by name will match anything with chrome/chromium in   #
# the title, not only chromium windows. It also matches a firefox #
# window open on this AU question, for example.                   #
###################################################################
mapfile -t windows < 
    <(wmctrl -pl | grep -f <(pgrep "chrom[e|ium]") | 
                   cut -d' ' -f1)

####################################
# Get the number of Chrome windows #
####################################
numofwins=${#windows[@]}

#########################################
# Initialize the x and y positions to 0 #
#########################################
x=0
y=0

#############################################
# Get 1/2 the number of windows, rounded up #
#############################################
halfwins=$(printf "%.f" "$(echo $numofwins/2 | bc -l | 
                           awk '{print int($1+0.5)}')")

######################################################
# If there's only one window, maximize/unmaximize it #
######################################################
[[ $numofwins -eq 1 ]] && 
    wmctrl -i -r "${windows[@]}" -b toggle,maximized_vert,maximized_horz &&  
    exit;

##########################################################################
# The height of each window will be the height of the display divided by #
# half the number of windows                                             #
##########################################################################
winheight=$(printf "%.f" "$(echo $height/$halfwins | bc -l)")

##################################################################
# The width of each window will be half the width of the display #
##################################################################
winwidth=$(($width/2))

##################################
# Iterate over each window found #
##################################
for winID in "${windows[@]}"
do
    ########################################
    # Increment a counter. This is used to #
    # know when we should change rows.     #
    ########################################
    let c++
    ###############################
    # Position the current window #
    ###############################
    wmctrl -i -r "$winID" -e 0,$x,$y,$winwidth,$winheight
    ##################################################
    # If the counter is a multiple of 2, change rows #
    ##################################################
    if [[ $((c % 2)) -eq 0 ]]
    then
        y=$((y+$winheight+2))
        x=0
    #######################################
    # If it isn't, move to the right only #
    #######################################
    else
        x=$((x+$winwidth+2))
    fi
done                                
0
ответ дан 15 May 2015 в 11:50

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

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