视觉切换器在提供上下文方面非常差劲。例如,浏览器窗口缩略图太小,很难区分,而且经常大部分都是空白的(请参见截图)。有没有一种能显示窗口标题列表的切换器?最好还能智能模糊自动完成(就像https://github.com/ctrlpvim/ctrlp.vim或https://github.com/junegunn/fzf):-)
按窗口名称排序列出窗口:
使用以下命令运行:
python3 <脚本> -win
输入要查找的窗口的首个字符或字符组合,然后按回车将窗口置于前台。
按应用程序排序列出窗口:
使用以下命令运行:
python3 <脚本> -app
按工作区排序列出窗口:
使用以下命令运行:
python3 <脚本> -ws
要从列表中选择一个项目,只需键入第一个字符。如果有更多符合输入字符的项目,箭头键将只浏览符合输入字符的项目:
或者:
设置非常简单:
这个脚本(绝对)需要 wmctrl
:
sudo apt-get install wmctrl
然后将下面的脚本复制到一个空文件中,保存为 list_windows.py
然后使用以下命令进行测试运行:
python3 /path/to/list_windows.py -app
python3 /path/to/list_windows.py -win
python3 /path/to/list_windows.py -ws
如果一切正常工作,请将一个或多个首选命令添加到一个或多个快捷键中:选择:系统设置 > "键盘" > "快捷方式" > "自定义快捷方式"。点击 "+" 并添加命令
(仍然是“未经打磨”的代码)
#!/usr/bin/env python3
import subprocess
import socket
import sys
arg = sys.argv[1]
# list (column) header titles and their (data) position in the produced window data list
cols = [["Workspace", -1], ["Application name", -2] , ["Window name", -3]]
# rearrange columns, depending on the chosen option
if arg == "-app":
cols = [cols[1], cols[2], cols[0]]
elif arg == "-ws":
cols = [cols[0], cols[2], cols[1]]
elif arg == "-win":
cols = [cols[2], cols[1], cols[0]]
# extract headers, list positions, to be used in the zenity list
col1 = cols[0][0]; i1 = cols[0][1]
col2 = cols[1][0]; i2 = cols[1][1]
col3 = cols[2][0]; i3 = cols[2][1]
# just a helper function
get = lambda cmd: subprocess.check_output([
"/bin/bash", "-c", cmd
]).decode("utf-8")
# analyse viewport data, to be able to calculate relative/absolute position of windows
# and current viewport
def get_spandata():
xr = get("xrandr").split(); pos = xr.index("current")
res = [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
spandata = get("wmctrl -d").split()
span = [int(n) for n in spandata[3].split("x")]
cols = int(span[0]/res[0]); rows = int(span[1]/res[1])
curr_vector = [int(n) for n in spandata[5].split(",")]
curr_viewport = int((curr_vector[1]/res[1])*cols + (curr_vector[0]/res[0])+1)
return {"resolution": res, "n_columns": cols, "vector": curr_vector, "current_viewport": curr_viewport}
posdata = get_spandata()
vector = posdata["vector"]; cols = posdata["n_columns"]
res = posdata["resolution"]; currvp = posdata["current_viewport"]
# function to distinguish "normal" windows from other types (like the desktop etc)
def check_window(w_id):
w_type = get("xprop -id "+w_id)
if " _NET_WM_WINDOW_TYPE_NORMAL" in w_type:
return True
else:
return False
# split windowdata by machine name
mach_name = socket.gethostname()
wlist = [[l.strip() for l in w.split(mach_name)] for w in get("wmctrl -lpG").splitlines()]
# split first section of window data
for i, w in enumerate(wlist):
wlist[i][0] = wlist[i][0].split()
# filter only "real" windows
real_wlist = [w for w in wlist if check_window(w[0][0]) == True]
# adding the viewport to the window's data
for w in real_wlist:
w.append(get("ps -p "+w[0][2]+" -o comm=").strip())
loc_rel = [int(n) for n in w[0][3:5]]
loc_abs = [loc_rel[0]+vector[0], loc_rel[1]+vector[1]]
abs_viewport = int((loc_abs[1]/res[1])*cols + (loc_abs[0]/res[0])+1)
abs_viewport = str(abs_viewport)+"*" if abs_viewport == currvp else str(abs_viewport)
w.append(abs_viewport)
# set sorting rules
if arg == "-app":
real_wlist.sort(key=lambda x: x[-2])
elif arg == "-ws":
real_wlist.sort(key=lambda x: x[-1])
elif arg == "-win":
real_wlist.sort(key=lambda x: x[-3])
# calculate width and height of the zenity window:
# height = 140px + 23px per line
h = str(140+(len(real_wlist)*23))
# width = 250px + 8px per character (of the longest window title)
w = str(250+(max([len(w[-3]) for w in real_wlist])*8))
# define the zenity window's content
cmd = "zenity --list --hide-column=4 --print-column=4 --title='Window list' "\
"--width="+w+" --height="+h+" --column='"+col1+"' --column='"+col2+"' --column='"+col3+\
"' --column='w_id' "+(" ").join([(" ").join([
'"'+w[i1]+'"','"'+w[i2]+'"','"'+w[i3]+'"','"'+w[0][0]+'"'
]) for w in real_wlist])
# finally, call the window list
try:
w_id = subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split("|")[0]
subprocess.Popen(["wmctrl", "-ia", w_id])
except subprocess.CalledProcessError:
pass
初步答案:
我刚刚发现了http://www.webupd8.org/2013/07/fuzzy-window-switcher-for-ubuntu.html,它链接到https://github.com/XCMer/fuzzy-window-switcher...看起来很有希望。
webupd8上的评论还指出Compiz的Scale插件具有类似的功能。开始输入时,窗口缩略图会被缩小以匹配搜索。而Scale Addons插件还允许显示所有窗口的标题。然而,标题在缩略图宽度处被截断(对于像编辑器和shell这样的窗口来说是不好的),并且搜索不是模糊的。
另一个在PyPI上的:http://pypi.python.org/pypi/windownow/