我知道Always on visible workspace但是我想要全部窗口在打开时将此作为默认设置,但也有少数例外。
我正在寻找的工作流程与它的工作方式完全相反。除少数(手动)例外外,在所有工作区中显示所有内容。
有可能吗?如果它需要一些脚本,我可能不会介意。
我正在运行带有 cinnamon 的 Ubuntu 17.04,但据我所知,此功能存在于 unity 和大多数桌面环境中。
答案1
有趣的案例。
我们需要考虑什么
这个概念并不复杂:只需将所有窗口设置为粘性,然而:
- 由于您想要排除某些应用程序,我们需要列出这些应用程序并检查窗口的窗口类,以决定是否应将它们设置为粘性(显示在所有工作区上)。
- 作为输出的窗口列表
wmctrl -l
还显示了一些窗口类型,例如 DOCK 和 DESKTOP,通常您不应该编辑它们的属性。 - 我们需要确保只设置新的把窗户粘好,防止不必要的油耗。
示例脚本(python)
在下面的脚本中:
运行两秒循环来将窗口列表与前一个窗口列表进行比较,使用:
wmctrl -l
然后从每一行中提取窗口 ID
随后,脚本运行
xprop -id <window_id>
我们可以在其中找到有关
_NET_WM_WINDOW_TYPE
和WM_CLASS
- 如果新窗口“通过”这些测试,即该窗口不属于任何排除的应用程序并且不属于任何排除的类型,则将其设置为粘性。
由于该脚本仅对新创建的窗口起作用,因此它不会给您的系统增加任何明显的负担。
剧本
#!/usr/bin/env python3
import subprocess
import time
# excluded applications
apps = ["gedit", "chromium", "monkey"]
# ignored window types
ignore = [
"= _NET_WM_WINDOW_TYPE_DOCK",
"= _NET_WM_WINDOW_TYPE_DESKTOP",
]
# just a helper
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except (subprocess.CalledProcessError, TypeError):
pass
# initiate windowlist
wins1 = []
while True:
# cycle time
time.sleep(2)
# initiate new list
new_wins = []
# get the most recent window list
windata = get(["wmctrl", "-l"])
if windata:
# extract window -ids
wins2 = [w.split()[0] for w in windata.splitlines()]
new = [w for w in wins2 if w not in wins1]
# check for excluded classes and window types
for w in new:
testdata = get(["xprop", "-id", w])
if all([
not any([ig in testdata for ig in ignore]),
not any([app in testdata for app in apps]),
]):
# set the passed windows to sticky
subprocess.Popen(
["wmctrl", "-i", "-r", w, "-b", "add,sticky"]
)
# refresh the window list for next cycle
wins1 = wins2
如何设置
确保
wmctrl
已安装:sudo apt install wmctrl
- 将脚本复制到一个空文件中,另存为
set_sticky.py
- 在脚本的头部,将
WM_CLASS
-ses 设置为排除(您可能想要删除 monkey,这是为了测试目的:)) 使用以下命令运行测试:
python3 /path/to/set_sticky.py
如果一切正常,您可以将其添加到启动应用程序中,但一定要添加一个小中断,以防止脚本在尚未准备好的桌面上中断:
/bin/bash -c "sleep 10 && python3 /path/to/set_sticky.py"
玩得开心 :)
笔记
我在 Ubuntu Budgie(mutter)上测试了 25 分钟,没有出现任何问题。它应该可以在任何窗口管理器上正常运行,但如果您遇到问题,请告知。