Как переместить все окна в другую рабочую область

Возможно переместить все окна (или все не минимизированные окна) формируют одну рабочую область другому?

Я знаю, что могу переместить одно окно в другую рабочую область с Shift+Ctrl+Alt+arrow, но это переместится только что одно сфокусированное окно.

9
задан 17 April 2016 в 09:38

3 ответа

Среды рабочего стола, не основанные на Compiz (XFCE, LXDE, GNOME, KDE ...)

Для этого можно использовать комбинацию wmctrl и xdotool . Сначала убедитесь, что установлены эти две утилиты:

sudo apt-get install xdotool wmctrl

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

while read i; do wmctrl -i -t 2 -r "$i"  ; done  < <(wmctrl -l | awk -v var=$(xdotool get_desktop) '{if ($2 == var) print $0;}' | cut -d' '  -f1)

Краткое описание используемых команд:

  • wmctrl -l | awk -v var = $ (xdotool get_desktop) '{if ($ 2 == var) print $ 0;}' | cut -d '' -f1

    Перечислить все окна, отфильтровать те, которые не находятся в текущей рабочей области, и извлечь их ID окна

  • wmctrl -i -t 2 -r "$ i"

    Переместить окно с идентификатором окна $ i в рабочее пространство 2.

  • все это упаковано в простой while read ... do; done цикл, который перебирает все окна на текущем рабочем столе.

Среды рабочего стола на основе Compiz (например, Unity)

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

4
ответ дан 23 November 2019 в 05:44

Unity: Что такое вьюпорты?

Ubuntu Unity использует вьюпорты - по сути, систему координат (с координатами 0,0 - левый верхний угол), где один огромный рабочий стол разделен на части, соответствующие разрешению вашего экрана. Координаты увеличиваются по мере перемещения вправо и вниз.

enter image description here

Система координат относительна. Если моя текущая область просмотра находится слева вверху, то все, что находится относительно этой области просмотра, будет иметь положительные значения ширины и высоты. Например, если мой текущий видовой экран находится сверху слева, то окно firefox в верхней средней рабочей области, которое вы видите выше, позиционируется по x со значением 1366 и y со значением 0 относительно верхнего левого видового экрана. Если мой активный видовой экран - верхний средний, окно терминала в верхнем левом видовом экране позиционируется в значении x -1327 60. Это ключевой вопрос для xdotool , потому что xdotool не работает с отрицательными числами.

Заметим также, что верхний левый угол текущего видового экрана всегда будет приниматься xdotool за координаты 0 0 . Это означает, что мы можем перемещать материал только вправо и вниз.

Заставляем xdotool работать в Unity

Теперь мы знаем, что xdotool может перемещать окна только относительно левого верхнего угла (т.е. вы всегда можете перемещать окно вниз и вправо, но никогда вверх и влево). Как мы можем заставить это работать для единства. Ну, основная идея заключается в следующем:

  1. Вычислить все окна на текущем видовом экране
  2. Переместиться на требуемый видовой экран, чтобы левый верхний угол принял координаты 0 0 на этом видовом экране
  3. Переместить все окна в заданные пользователем координаты видового экрана
  4. Вернуться в старый видовой экран (необязательно, можно следовать за окнами)

Сценарное решение

Приведенный ниже сценарий выполняет именно ту процедуру, которая описана выше. Он может быть вызван с флагом -v для ручного указания координат, или вы можете использовать флаг -g для вызова диалога GUI. Флаг -f укажет скрипту также переключить видовой экран; если этот флаг не используется - вы останетесь на текущем видовом экране и будут перемещаться только окна

Получение скрипта

Можно скопировать исходный код из этого поста напрямую или через github, используя следующие шаги:

  1. sudo apt-get install git
  2. cd /opt ; sudo git clone https://github. com/SergKolo/sergrep.git
  3. sudo chmod -R +x sergrep

Файл скрипта будет /opt/sergrep/move_viewport_windows.sh

Чтобы привязать скрипт к сочетанию клавиш, обратитесь к Как привязать .sh файлы к сочетанию клавиш?

Обратите внимание, что wmctrl и xdotool необходимы для работы этого скрипта. правильно. Вы можете установить их с помощью sudo apt-get install xdotool и wmctrl

Исходный код

#!/usr/bin/env bash
#
###########################################################
# Author: Serg Kolo , contact: 1047481448@qq.com 
# Date: April 17 2016
# Purpose: Move all windows on the current viewport
#          to a user-defined one
# Written for:
# Tested on: Ubuntu 14.04 LTS , Unity 7.2.6
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use, copy, modify, and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.

get_active_viewport()
{
  xprop -root -notype _NET_DESKTOP_VIEWPORT
}

get_screen_geometry()
{
 xwininfo -root | awk '/-geometry/{gsub(/+|x/," ");print $2,$3}'  
}

current_wins()
{  
   HEX="$(wmctrl -lG | \
   awk -v xlim="$XMAX" -v ylim="$YMAX" \
      'BEGIN{printf "ibase=16;"} $3>0 && $3<xlim  && $4>0 && $4<ylim \
      { gsub(/0x/,""); printf "%s;",toupper($1)  } ')"
   echo $HEX | bc | tr '\n' ' '
}

gui_selection()
{
  SCHEMA="org.compiz.core:/org/compiz/profiles/unity/plugins/core/"
  read swidth sdepth  <<< "$(get_screen_geometry)"
  vwidth=$(gsettings get $SCHEMA hsize)
  vheight=$(gsettings get $SCHEMA vsize)

 width=0
 for horizontal in $(seq 1 $vwidth); do
    height=0 
    for vertical in $(seq 1 $vheight);  do

      array+=( FALSE  )
      array+=( $(echo "$width"x"$height") )

    height=$(($height+$sdepth))
    done
 width=$(($width+$swidth))
 done

 zenity --list --radiolist --column="" --column "CHOICE" ${array[@]} --width 350 --height 350 2> /dev/null
}

print_usage()
{
cat << EOF
move_viewport_windows.sh [-v 'XPOS YPOS' ] [-g] [-f ] [-h]

Copyright Serg Kolo , 2016

The script gets list of all windows on the current Unity 
viewport and moves them to user-specified viewport. If
ran without flags specified, script prints this text

-g flag brings up GUI dialog with list of viewports

-v allows manually specifying viewoport. Argument must be
   quoted, X and Y position space separated

-f if set, the viewport will switch to the same one where
   windows were sent

-h prints this text

** NOTE ** 
wmctrl and xdotool are required for this script to work
properly. You can install them via sudo apt-get install
xdotool and wmctrl

EOF
}

parse_args()
{
  if [ $# -eq 0  ];then
    print_usage
    exit
  fi
  while getopts "v:ghf" opt
 do
   case ${opt} in
     v) NEWVP=${OPTARG}
        ;;
     g) NEWVP="$(gui_selection | tr 'x' ' ' )"
        [ -z "$NEWVP" ] && exit 1
        ;;
     f) FOLLOW=true
        ;; 
     h) print_usage
        exit 0
        ;;
     \?)
      echo "Invalid option: -$OPTARG" >&2
      ;;
    esac
  done
  shift $((OPTIND-1))
}

main()
{
 # Basic idea:
 #-------------------
 # 1. get current viewport and list of windows
 # 2. go to viewport 0 0 and move all windows from list
 #    to desired viewport
 # 3. go back to original viewport or follow the windows,
 #    depending on user choice
 # 4. Tell the user where they are currently

 local FOLLOW
 local NEWVP # coordinates of desired viewport
 local XMAX YMAX # must be two vals for awk to work
 local OLDVP=$(get_active_viewport | awk -F '=' '{sub(/,/," ");print $2}' )

 parse_args "$@"

 read XMAX YMAX  <<< "$(get_screen_geometry)" # move to getopts

 windows=( $(current_wins) )

 xdotool set_desktop_viewport 0 0 
 for win in ${windows[@]} ; do
    echo "$win"
    xdotool windowmove $win $NEWVP
 done
 # sleep 0.25 # uncomment if necessary

 if [ $FOLLOW  ]; then
     xdotool set_desktop_viewport $NEWVP
 else
     xdotool set_desktop_viewport $OLDVP
 fi

 sleep 0.25 # delay to allow catching active viewport
 notify-send "current viewport is $(get_active_viewport | awk -F '=' '{sub(/,/," ");print $2}' )"
 exit 0
}
main "$@"

Демо

Webm запись скрипта в действии:

https://www.youtube.com/watch?v=cJMlC41CWWo

Проблемы

Из-за плагина Unity grid, который отвечает за привязку окон, скрипт не может перемещать максимизированные, или привязанные вправо/влево окна. Будет сделана попытка добавить мгновенную отмену и сброс этого плагина, чтобы скрипт работал со всеми окнами, но поскольку отмена и сброс имеют временную задержку, от этой идеи можно отказаться. Если вы хотите, чтобы скрипт работал со всеми окнами, установите unity-tweak-...tool и снимите привязку окон в опциях диспетчера окон.

6
ответ дан 23 November 2019 в 05:44

Я сделал что-то похожее на подход glutanimate

Вот bash скрипт, который это делает:

for window in `wmctrl -l | awk -v var=$(xdotool get_desktop) '{if ($2 == var) print $0;}' | cut -d' '  -f1`
do 
        target=$(($1-1))
        wmctrl -i -t $target -r "$window"
done

wmctrl -s $target

Просто запустите его, передав целевое окно (индекс на основе 1) в качестве аргумента, как показано ниже: bash move_ws.sh 3 (переместить все текущие окна в рабочее пространство с индексом 3 (считая от 1))

Однако я подумал, что вместо того, чтобы отправлять все окна в некоторое рабочее пространство i. Я подумал, что было бы более полезно поменять местами соседние рабочие пространства.

Например, если вы сейчас находитесь в рабочем пространстве 2 и ваши рабочие пространства выглядят следующим образом (слева направо / сверху вниз):

1
2
3
4

Вы можете запустить мой скрипт bash swap_ws.sh down (или просто использовать сочетание клавиш, как это сделал я). И 2 поменяется местами с 3:

1
3
2
4

Теоретически, рабочие пространства не меняются местами, но все окна меняются. Вы также можете использовать bash swap-ws.sh up и это работает как ожидалось.

Вот код. Только не забудьте запустить его с помощью bash:

cur_ws=$(xdotool get_desktop)
max_ws=$(xdotool get_num_desktops)

# determine destination workspace based on current workspace
if [ "$1" = "up" ] && [ $cur_ws -gt 0 ]; then
    next_ws=$((cur_ws-1))        
elif [ "$1" = "down" ] && [ $cur_ws -lt $max_ws ]; then
    next_ws=$((cur_ws+1))
else 
    exit 0
fi

source_win=$(wmctrl -l | grep -oE "[0-9a-f]x[0-9a-f]+\s+$cur_ws" | cut -f1 -d" ")
target_win=$(wmctrl -l | grep -oE "[0-9a-f]x[0-9a-f]+\s+$next_ws" | cut -f1 -d" ")

# push each window from current to next ws
for win in $source_win; do
    wmctrl -i -r "$win" -t "$next_ws"
done

# pull each window from next ws to current
for win in $target_win; do
    wmctrl -i -r "$win" -t "$cur_ws"
done

# go to target workspace
wmctrl -s $next_ws

NOTE: Этот скрипт работает лучше, если вы используете статическое количество рабочих пространств (вы можете изменить это в Tweaks, если вы используете GNOME)

0
ответ дан 28 July 2021 в 15:29

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

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