我想知道是否有任何方法可以使用终端命令来实现 Unity 中 Ctrl-Alt-Keypad 快捷键的效果?我想要一个命令,将 GUI 窗口设置为屏幕大小的一半,左对齐或右对齐。
作为背景,我正在编写一个在登录后运行的脚本。它使用 Zenity 询问我是否要打开我的开发环境(并排的 GVim 和 IPython)。我一直试图通过在set lines= columns=
我的.gvimrc
和在我的中c.IPythonWidget.width =
使用来实现这些程序的两个大小相同的窗口。但是,这种方法存在一些问题。c.IPythonWidget.height =
ipython_qtconsole_config.py
答案1
你会遇到什么
如果你想先调用一个应用程序,然后将其窗口放置在特定的位置和大小,则调用应用程序和窗口实际出现的那一刻,是不可预测的。如果您的系统处于繁忙状态,则该时间可能比空闲时长得多。
您需要一种“智能”的方法来确保定位/调整大小在窗口之后(立即)完成出现。
调用应用程序的脚本,等待它出现并将其定位在屏幕上
使用下面的脚本,您可以调用一个应用程序并使用以下命令设置它应出现的位置和大小:
<script> <application> <x-position> <y-position> <h-size> <v-size>
举几个例子:
调用
gnome-terminal
并调整其窗口大小为 50%,然后将其放置在右半部分:<script> gnome-terminal 840 0 50 100
要调用
gedit
,请将其窗口放在左侧和调用gnome-terminal
,将其放在右侧(设置其v-size
46% 以在窗口之间留出一点空间):<script> gedit 0 0 46 100&&<script> gnome-terminal 860 0 46 100
要调用 Inkscape,请将其窗口放在屏幕的左侧/上部四分之一处:
<script> inkscape 0 0 50 50
脚本及其使用方法
安装
xdotool
和wmctrl
。我使用了两个都因为调整大小wmctrl
可能会导致(具体来说)出现一些特殊情况Unity
。sudo apt-get install wmctrl sudo apt-get install xdotool
- 将下面的脚本复制到一个空文件中,将其保存为
setwindow
(无扩展名)~/bin
;如有必要,创建目录。 - 使脚本可执行(!)
- 如果您刚刚创建
~bin
,请运行:source ~/.profile
使用以下命令测试运行脚本(例如)
setwindow gnome-terminal 0 0 50 100
换句话说:
setwindow <application> <horizontal-position> <vertical-position> <horizontal-size (%)> <vertical-size (%)>
如果一切正常,请在需要的地方使用该命令。
剧本
#!/usr/bin/env python3
import subprocess
import time
import sys
app = sys.argv[1]
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
subprocess.Popen(["/bin/bash", "-c", app])
while t < 30:
ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
if app in p and w[2] in p] for w in ws2]
if len(procs) > 0:
w_id = procs[0][0][1]
cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
cmd3 = "xdotool windowsize --sync "+procs[0][0][1]+" "+sys.argv[4]+"% "+sys.argv[5]+"%"
cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[2]+" "+sys.argv[3]
for cmd in [cmd1, cmd2, cmd3, cmd4]:
subprocess.call(["/bin/bash", "-c", cmd])
break
time.sleep(0.5)
t = t+1
它能做什么
当调用该脚本时,它:
- 启动应用程序
- 关注窗口列表(使用
wmctrl -lp
) - 如果出现新窗口,它会检查新窗口是否属于被调用的应用程序(使用
ps -ef ww
,将窗口的 pid 与应用程序的 pid 进行比较) - 如果是,它会根据您的参数设置大小和位置。如果应用程序在大约 15 秒内没有“显示”,则脚本会假定该应用程序由于错误不会运行。然后脚本会终止,以防止无限期地等待新窗口。
小问题
wmctrl
在 Unity 中,当您使用或(重新)定位和(重新)调整窗口大小时xdotool
,窗口将始终与屏幕边框保持较小的间距,除非您将其设置为 100%。您可以在上图 (3) 中看到;当窗口inkscape
放置在x
位置 0 时,您仍然可以看到 Unity Launcher 和窗口之间的微小间距inkscape
。
答案2
你想要的实际命令是这样的
wmctrl -r :ACTIVE: -b add,maximized_vert &&
wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
这将使当前窗口占据屏幕的一半(更改$HALF
为屏幕的尺寸)并对齐到左侧。要对齐到右侧,请使用
wmctrl -r :ACTIVE: -b add,maximized_vert &&
wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1
您也可以使用 来wmctrl
获取您感兴趣的窗口的 ID,而不是使用:ACTIVE:
。不过我无法提供帮助,因为这取决于所讨论的窗口。请查看man wmctrl
了解更多信息。
我为此编写了一个脚本。我不使用 Unity,因此不能保证它能与 Unity 兼容,但我认为没有理由不兼容。它需要安装wmctrl
、xdpyinfo
和:disper
sudo apt-get install wmctrl x11-utils disper
然后,将下面的脚本保存为~/bin/snap_windows.sh
,使用以下命令使其可执行chmod a+x ~/bin/snap_windows.sh
,然后您就可以运行
snap_windows.sh r
捕捉到右侧。l
用于左侧,不使用参数来最大化窗口。请注意,它在当前窗口上运行,因此如果您希望它在终端以外的任何窗口上运行,则需要为其分配快捷方式。
该脚本比您要求的要复杂一些,因为我编写它是为了在单显示器和双显示器设置上运行。
#!/usr/bin/env bash
## If no side has been given, maximize the current window and exit
if [ ! $1 ]
then
wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
exit
fi
## If a side has been given, continue
side=$1;
## How many screens are there?
screens=`disper -l | grep -c display`
## Get screen dimensions
WIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'`;
HALF=$(($WIDTH/2));
## If we are running on one screen, snap to edge of screen
if [ $screens == '1' ]
then
## Snap to the left hand side
if [ $side == 'l' ]
then
## wmctrl format: gravity,posx,posy,width,height
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
## Snap to the right hand side
else
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1
fi
## If we are running on two screens, snap to edge of right hand screen
## I use 1600 because I know it is the size of my laptop display
## and that it is not the same as that of my 2nd monitor.
else
LAPTOP=1600; ## Change this as approrpiate for your setup.
let "WIDTH-=LAPTOP";
SCREEN=$LAPTOP;
HALF=$(($WIDTH/2));
if [ $side == 'l' ]
then
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$LAPTOP,0,$HALF,-1
else
let "SCREEN += HALF+2";
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$SCREEN,0,$HALF,-1;
fi
fi
答案3
您可以使用 来执行此操作xdotool
。
要安装,xdotool
您可以运行:
sudo apt-get update && sudo apt-get install xdotool
然后要将 ++ 按键发送Ctrl到终端窗口Alt,您可以运行:<keypad_key>X
xdotool key Ctrl+Alt+<keypad_key_value>
*<keypad_key_value> = 以下列表中的键盘键值
要运行 GUI 程序并将击键发送到其X
窗口(在本例中是命令执行时的活动窗口xdotool
),您可以运行:
<command> && window="$(xdotool getactivewindow)" xdotool key --delay <delay> --window "$window" <keypad_key_value>
*<command> = 打开要发送击键的窗口的命令;<delay> = 发送击键前等待的时间(以毫秒为单位);<keypad_key_value> = 下表中的键盘键值
请注意,在大多数情况下,您需要将发出的命令作为独立进程运行(例如,通过运行nohup <command> &
而不是<command>
在上面的示例中),否则直到执行完成xdotool
才会运行。<command>
您还需要设置一些延迟,否则键击将在目标窗口完全加载之前发送X
(大约延迟一下500ms
就可以了)。
可能的值包括<keypad_key_value>
:
- 0:
90
- 1:
87
- 2:
88
- 3:
89
- 4:
83
- 5:
84
- 6:
85
- 7:
79
- 8:
80
- 9:
81
根据经验法则,要找出环境中键盘上任何键的值X
,可以运行xev
并按下该键以在终端内输出其值。
答案4
我没有权限直接评论 Jacob Vlijm 的精彩帖子,但我修改了脚本以允许使用参数启动应用程序(使用setwindow
with 时必须使用gedit --new-window
)。更改:
if app in p and w[2] in p] for w in ws2]
到:
if app.split()[0] in p and w[2] in p] for w in ws2]