如何将所有窗口移到另一个工作区


8

是否可以将所有窗口(或所有未最小化的窗口)从一个工作区移动到另一个工作区?

我知道我可以使用Shift+ Ctrl+ Alt+ 将一个窗口移动到其他工作区arrow,但是它将仅移动那个集中的窗口。


您仍然对Unity解决方案感兴趣吗?
Jacob Vlijm

是的,我想要Unity的解决方案。抱歉,我没有完全指定我使用的是Unity
betatester07

你注意到这个了吗?我没有尝试,不知道它是否仍然有效。如果没有,我可以考虑在快捷键组合下选择其他方法。
Jacob Vlijm 2015年

啊,对不起,这是一个单一的窗口,将调查它!
Jacob Vlijm 2015年

一直在努力,并拥有“某种”工作脚本。但是,随机发生的问题使其几乎不可用。如果发现原因,它将发布它。
Jacob Vlijm'3

Answers:


5

Unity:什么是视口?

Ubuntu Unity使用视口-基本上是一个坐标系(坐标0,0为左上角),其中一个巨大的桌面细分为适合您屏幕分辨率的块。当您向右和向下移动时,坐标的价值会增加。

在此处输入图片说明

坐标系是相对的。如果我当前的视口在左上角,则相对于该视口的所有内容均为正值,以width和height为增量。例如,如果我当前的视口位于最左上角,则您在上方看到的顶部中间工作区中的Firefox窗口相对于最左上的视口位于x值1366和y值0处。如果我的活动视口在顶部中间视口中,则最左上视口中的终端窗口位于x值-132760。 这是的关键问题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文件绑定到键盘组合?

请注意,此脚本是wmctrlxdotool,才能正常运行。您可以通过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在“窗口管理器”选项下安装并取消设置窗口捕捉。


惊人的是这样一个专门的答案如何得到只有2-3 upvotes ...
约整洁的坚果

3

基于非Compiz的桌面环境(XFCE,LXDE,GNOME,KDE ...)

您可以使用的组合wmctrlxdotool这一点。首先,请确保已安装以下两个实用程序:

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"

    将具有窗口ID的窗口移动$i到工作区2。

  • 所有这些都打包在一个简单的while read ... do; done循环中,该循环遍历当前桌面上的所有窗口

基于Compiz的桌面环境(例如Unity)

由于Compiz(Unity的窗口管理器)不使用传统意义上的桌面,因此很难找到适用于Unity等桌面环境的解决方案。


谢谢,看起来不错。但是我正在使用Unity,并希望有一些简单的解决方案。但是正如您提到的,Unity的解决方案会更加困难
betatester07

只是一小段话,“将窗口ID为$ i的窗口移动到工作区2”中的工作区2。实际上是第三个工作空间,而不是第二个工作空间,因为第一个工作空间以零开始。因此,如果只有两个工作区,该脚本可能看起来不起作用。
Mohamad Fakih
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.