视觉切换器在提供上下文方面表现很差。例如,浏览器窗口缩略图太小,难以区分,而且通常大多数都是空白的(见屏幕截图)。
有没有显示窗口标题列表的切换器?最好有智能模糊自动完成功能(例如https://github.com/ctrlpvim/ctrlp.vim或者https://github.com/junegunn/fzf):-)
答案1
“自制产品”的乐趣在于,你可以随心所欲地制作产品。但可能的缺点是,如果项目很有趣,你很容易沉迷其中……
下面的脚本可能就是这种情况 :)。虽然我更希望添加一个关于其“内部”工作原理的详细解释,但这是一个“随时可用”的解决方案。虽然我添加了一些注释行,但很难对代码给出简单的内部解释。不过,它似乎接近您想要的。
这是什么
该脚本是一个纯基于文本的解决方案,用于列出所有打开的“正常”应用程序窗口(并提升一个选定的窗口),但它有许多选项:
列出窗口,按以下方式排序窗口名称:
使用以下命令运行:
python3 <script> -win
键入所需窗口的第一个字符,然后按回车键将窗口置于前面。
列出窗口,按以下方式排序应用:
使用以下命令运行:
python3 <script> -app
列出窗口,按以下方式排序工作区:
使用以下命令运行:
python3 <script> -ws
可以看到,显示的列有:窗口名称,应用,工作区。预设的排序列始终是第一个。
模糊?
要从列表中选择一个项目,只需键入第一个字符。如果有更多项目符合键入的字符,则箭头键将仅浏览符合键入的字符的项目:
此外:
工作空间指示
当前工作区标有*
:例如,如果您看到2*
,则表示窗口位于工作区上2
和 工作区2
是当前工作区。无论您有多少个工作区,这都有效。
窗口大小
选择窗口自动设置为窗口的(最长)名称和要显示的窗口数量,例如:
或者:
如何使用
设置非常简单:
该脚本(肯定)需要
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
答案2
暂定答案:
我刚刚发现http://www.webupd8.org/2013/07/fuzzy-window-switcher-for-ubuntu.html链接到https://github.com/XCMer/fuzzy-window-switcher..这看起来很有希望。
webupd8 上的评论还指出,Compiz规模插件具有类似的功能。开始输入,窗口缩略图就会缩小以匹配搜索。扩展插件插件还允许显示所有窗口的窗口标题。但是标题在缩略图宽度处被截断(这对于编辑器和 shell 等标题较长的窗口来说很糟糕),并且搜索不模糊。
PyPI 上的另一个:http://pypi.python.org/pypi/windownow/