答案1
编辑
(新答案)
完毕。
下面的答案现在以完善的形式提供,作为指标,作为 Trusty、Xenial、Yakkety 和 Zesty 的 ppa:
sudo apt-add-repository ppa:vlijm/windowspy
sudo apt-get update
sudo apt-get install windowspy
指示器(包括预览窗口)现在电量不足。选项包括设置窗口、设置窗口边框大小/颜色、窗口大小。
与此同时,我发现关注 AU 窗口很有用;看看是否有任何消息:)
旧答案
(第一秒粗略的概念)
在另一个工作区上最小化显示窗口
令我(大为)惊讶的是,它可以是有效地完成了,无论是使用诡计还是欺骗;在另一个工作区上有一个更新的窗口表示。不是适合观看电影,绝对足以关注其他地方的窗口(例如:我的电视卡窗口):
实践中如何运作
在窗口前面,按下快捷键:
(窗口将最小化)
移动到另一个工作区,再次按下快捷键,将出现一个小窗口,每 4 秒更新一次:
该窗口始终显示在其他窗口之上。窗口本来是 300px(宽度),但可以设置为任意大小。
要结束它,请(再次)按下快捷键。小窗口将关闭,您将移动到原始窗口的视口,该窗口将再次出现,未最小化。
脚本
控制脚本
#!/usr/bin/env python3 import subprocess import os import sys import time # paths imagepath = os.path.join(os.environ["HOME"], ".showcase") wfile = os.path.join(imagepath, "currentwindow") vpfile = os.path.join(imagepath, "last_vp") # setup path if not os.path.exists(imagepath): os.mkdir(imagepath) def get(command): try: return subprocess.check_output(command).decode("utf-8").strip() except subprocess.CalledProcessError: pass def get_vp(): open(vpfile, "wt").write(get(["wmctrl", "-d"]).split()[5]) def run(command): subprocess.Popen(command) def convert_tohex(widxd): return widxd[:2]+((10-len(widxd))*"0")+widxd[2:] def check_windowtype(wid): check = get(["xprop", "-id", wid]) return not any([s in check for s in [ "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_DESKTOP"]]) def edit_winprops(wid, convert=True): run(["xdotool", "windowminimize", wid]) if convert: widxd = convert_tohex(hex(int(wid))) else: widxd = wid run(["wmctrl", "-i", "-r", widxd, "-b", "add,sticky"]) get_vp() open(os.path.join(imagepath, "currentwindow"), "wt").write(widxd) def initiate_min(): # if not, minmize window, write the file wid = get(["xdotool", "getactivewindow"]) if check_windowtype(wid): edit_winprops(wid) else: pidinfo = [l.split() for l in wlist.splitlines()] match = [l for l in pidinfo if all([ get(["ps", "-p", l[2], "-o", "comm="]) == "VirtualBox", not "Manager" in l])] if match: edit_winprops(match[0][0], convert=False) # windowlist wlist = get(["wmctrl", "-lp"]) if "Window preview" in wlist: # kill the miniwindow pid = get(["pgrep", "-f", "showmin"]) run(["kill", pid]) window = open(wfile).read().strip() viewport = open(vpfile).read().strip() run(["wmctrl", "-o", viewport]) time.sleep(0.3) run(["wmctrl", "-i", "-r", window, "-b", "remove,sticky"]) run(["wmctrl", "-ia", window]) os.remove(wfile) else: # check if windowfile exists wfileexists = os.path.exists(wfile) if wfileexists: # if file exists, try to run miniwindow window = open(wfile).read().strip() if window in wlist: # if the window exists, run! run(["showmin", window]) else: # if not, minmize window, write the file initiate_min() else: # if not, minmize window, write the file initiate_min()
窗口表示
#!/usr/bin/env python3 import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject from PIL import Image import os import subprocess import time from threading import Thread import sys wid = sys.argv[1] xsize = 300 imagepath = os.path.join(os.environ["HOME"], ".showcase") if not os.path.exists(imagepath): os.mkdir(imagepath) img_in = os.path.join(imagepath, "image.png") resized = os.path.join(imagepath, "resized.png") def get_img(): subprocess.Popen([ "import", "-window", wid, "-resize", str(xsize), resized ]) get_img() class Splash(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Window preview") maingrid = Gtk.Grid() self.add(maingrid) self.image = Gtk.Image() # set the path to the image below self.resized = resized self.image.set_from_file(self.resized) maingrid.attach(self.image, 0, 0, 1, 1) maingrid.set_border_width(3) self.update = Thread(target=self.update_preview) self.update.setDaemon(True) self.update.start() def update_preview(self): while True: get_img() time.sleep(3) GObject.idle_add( self.image.set_from_file, self.resized, priority=GObject.PRIORITY_DEFAULT ) def miniwindow(): window = Splash() window.set_decorated(False) window.set_resizable(False) window.set_keep_above(True) window.set_wmclass("ShowCase", "showcase") window.connect("destroy", Gtk.main_quit) GObject.threads_init() window.show_all() window.move(70, 50) Gtk.main() miniwindow()
如何使用
安装
python3-pil
,xdotool
然后wmctrl
sudo apt-get install xdotool wmctrl python3-pil
如果目录尚不存在,则创建该目录
~/bin
。- 复制脚本 1,即控制脚本,与
showcase_control
中的(完全相同)(无扩展名)相同~/bin
,并且使其可执行。 - 复制脚本 2,即迷你窗口脚本,与
showmin
中的(完全一样)(无扩展名)相同~/bin
,并且使其可执行。 注销并重新登录,并将以下命令添加到您选择的快捷方式中:
showcase_control
选择:系统设置 > “键盘” > “快捷键” > “自定义快捷键”。点击“+”并添加命令:
showcase_control
它应该可以工作!
- 按一次键抓取当前窗口
- 移动到你想要迷你窗口的其他工作区
- 再次按下显示迷你窗口
- 再次按下可返回到原始工作区,(自动)取消最小化原始窗口并关闭迷你窗口。
缺点?
目前的设置是添加一些适用于您的处理器。然而,在我的(非常)旧系统上,它(平均)增加了大约 4-5%,我估计,我没有注意到任何方式。
更新:事实证明,
import
可以一步调整图像大小,再加上获取窗口图像。这意味着处理器负载大幅减少。同时刷新时间更短(现在为 3 秒),但“成本”仍然较低。
解释
- 我的出发点是 OP 提到的他想使用该选项来关注另一个工作区上的窗口,等待某件事完成。
- 尽管字面上地在另一个工作区上拥有一个窗口的精确(微型)副本似乎是不可能的,我们能一旦我们有了窗口 ID,就可以使用 -command 为现有窗口创建图像
import
。虽然这两者都适用于最小化窗口或无焦点窗口,但有一个问题:窗口需要在当前工作区。 - 诀窍是暂时(使用迷你窗口时)使窗口“粘滞” (几乎在所有工作区上可用)
wmctrl
,但同时最小化。 - 由于一切都是自动完成的,区别有效地是无,因为返回初始视口、取消粘性原始窗口以及取消最小化它都是自动完成的。
简而言之:
- 按一次快捷键:目标窗口变为粘性,但最小化
- 再次按下它(大概在另一个工作区):左上角会出现一个小型的窗口版本,每四秒更新一次。
- 再次按下:迷你窗口关闭,桌面移动到窗口的初始工作区,窗口恢复为非粘性且非最小化。
专门针对 VirtualBox
当 VBox 窗口在前面时,Ubuntu 快捷键被禁用了(!),因此需要以另一种方式启动控制脚本。下面是一些简要的。
选项1
我编辑了控制脚本。现在仅有的对于 VirtualBox 来说:
点击任何地方在桌面上,然后按下快捷键。之后,只需使用快捷键即可显示窗口并退出。
解释:如果窗口类型为“桌面”,则控制脚本将退出,因为您不想最小化桌面。现在,如果当前活动窗口是桌面,则脚本首先查找可能存在的 VirtualBox 窗口作为目标。
选项 2
复制下面的图标(右键->另存为),另存为
minwinicon.png
将以下行复制到一个空文件中,并将其保存
minwin.desktop
为~/.local/share/applications
:[Desktop Entry] Type=Application Name=Window Spy Exec=showcase_control Icon=/path/to/minwinicon.png StartupNotify=false
您需要注销并重新登录,以便启动器“找到”本地
~/bin
路径!
将图标拖到启动器上即可使用它。
第二种解决方案有一个重要的缺点:从启动器使用它后,它会持续闪烁几秒钟,等待窗口出现。在此期间,再次点击不会有任何效果。能得到解决,如上所述这里,但将其包含在这个答案中确实会使其太长。如果您想使用选项二,请查看链接。