我可以有一个窗口,显示另一个工作区的实时预览吗?


29

是否可以镜像一个工作空间的活动部分,以便它在当前工作空间中作为可移动的窗口可见?

前几天,我在Ubuntu 16.04主机上运行了Windows 10 VM,这花费了很长时间才能完成更新。我一直在Ubuntu上通过Expo(Super+ S)检查其进度。那让我想到这个问题很可能已经解决了,因为诸如simplescreenrecorder之类的工具可以配置为仅记录屏幕的一部分。但是,我不知道用于Google搜索的正确术语。

我想以浮动窗口(带有实时更新)的形式在下面的300x150屏幕截图中查看,无论哪个工作空间是最新的。

在此处输入图片说明


1
@serg在这里为您提供一个新项目
Rinzwind '16

@Rinzwind,您一定讨厌Serg ...我们(俩人)以前都在看这样的事情,没有成功。
Jacob Vlijm '16

1
这次我什至给了赏金:=)@JacobVlijm
Rinzwind

将会是一个很酷的功能:)在VM的情况下没有帮助,但是有一个针对终端应用程序的解决方案:使用Konsole。它有两个有用的选项:“在活动时通知”和“在沉默时通知”。第一个提示会在终端中显示新行时向您发送通知(在使用tail -F file | grep pattern日志警告某些事件时很有用),第二个提示会在自上一行写入后已有一段时间时向您发送通知(知道构建何时结束)。
kik

@Rinzwind废话,它将起作用...
Jacob Vlijm

Answers:


26

编辑

(新答案)

完成。
下面的答案现在可以以抛光的形式提供,作为指标,例如Trusty,Xenial,Yakkety和Zesty的ppa:

sudo apt-add-repository ppa:vlijm/windowspy
sudo apt-get update
sudo apt-get install windowspy

指示器(包括预览窗口)现在的果汁含量很低。选项包括设置窗口,设置窗口边框大小/颜色,窗口大小。

在此处输入图片说明

同时,我发现关注非盟窗口很有用。看看是否有任何消息:)


老答案

第一个第二个粗略概念)

最小化另一个工作区上的窗口表示

令我自己大吃一惊的是,可以有效地做到这一点,无论是通过欺骗还是欺骗手段。具有另一个工作空间上的窗口的更新表示。适合看电影,绝对足以吸引其他地方的窗户(例如:我的电视卡窗户):

在实践中如何运作

  1. 在窗口位于前面的情况下,按快捷键:

    在此处输入图片说明

    (窗口将最小化)

  2. 移至另一个工作区,再次按快捷键,将出现窗口的小图示,每4秒更新一次:

    在此处输入图片说明

    该窗口始终显示在其他窗口的顶部。实际上,窗口为300px(宽度),但可以设置为任何大小。

  3. 要结束它,请按(再次)快捷键。小窗口将关闭,您将移至原始窗口的视口,该视口将再次最小化。

脚本

  1. 控制脚本

    #!/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()
  2. 窗口表示

    #!/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()

如何使用

  1. 安装python3-pilxdotool然后wmctrl

    sudo apt-get install xdotool wmctrl python3-pil
    
  2. 创建目录(如果尚不存在)~/bin

  3. 复制脚本1,他将脚本控制为(完全)showcase_control(无扩展名)~/bin,并使其可执行
  4. 将脚本2(迷你窗口脚本)复制为(完全)showmin(无扩展名)~/bin,并使其可执行
  5. 注销并重新登录,然后将以下命令添加到您选择的快捷方式中:

    showcase_control
    

    选择:系统设置>“键盘”>“快捷方式”>“自定义快捷方式”。单击“ +”并添加命令:

    showcase_control
    

    它应该工作!

    • 按键一次即可获取当前窗口
    • 移到您想要迷你窗口的其他工作区
    • 再按一次以显示迷你窗口
    • 再按一次可返回到原始工作区,(自动)取消最小化原始窗口并关闭mini-one。

缺点?

  • 目前的设置为您的处理器增加了一些工作。但是,在我的(非常旧的)系统上,它增加了(平均)appr。4-5%我想,这是我没有在发现任何方式。

    更新:事实证明import可以一步调整图像大小,并获取窗口图像。这意味着处理器负载将大大降低。同时,刷新时间更短(现在为3秒),但仍具有较低的“成本”。

说明

  • 我的出发点是OP提到他想使用该选项来盯着另一个工作区的窗口,等待其中任何一个完成的方式。
  • 虽然从字面上看不可能在另一个工作空间上有一个窗口的精确(微型)副本,但是一旦有了窗口ID ,我们就可以使用import-command 制作现有窗口的图像。尽管这两种方法都可以在最小化的窗口或没有焦点的窗口上工作,但是存在一个问题:窗口必须位于当前工作空间上
  • 然后,诀窍是使用临时使窗口(使用微型窗口时)“变为粘性”(实际上在所有工作空间中都可用)wmctrl,同时将窗口最小化。
  • 由于所有操作都是自动完成的,因此区别实际上是没有的,因为还返回了初始视口,所以“自动粘贴”原始窗口并将其最小化是自动完成的。

简而言之:

  1. 一次按下快捷方式:目标窗口变粘,但最小化
  2. 再次按下它(大概是在另一个工作空间上):窗口的一个小型迷你版出现在左上角,每四秒钟更新一次。
  3. 再次按下它:迷你窗口关闭,桌面移至该窗口的初始工作区,该窗口恢复原状且未最小化。

专门用于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路径!
    将图标拖到启动器上以使用它。

第二种解决方案有一个重要的缺点:在启动器中使用它后,它将持续闪烁几秒钟,等待出现一个窗口。在此期间,再次单击不会产生任何效果。这可以解决的,如描述在这里,但包括在这个答案能真正使太长。如果要使用选项二,请查看链接。


因此,好老的import可以做到,而gnome截屏不能做到。非常非常有趣。我很想知道他们的工作方式之间到底有什么区别
Sergiy Kolodyazhnyy 2016年

@Serg是的,我真的很惊讶,以为
仅靠

1
@ThatGuy正在处理它:)
Jacob Vlijm '16

1
@jymbob感谢您的评论!毫无疑问,它们在系统中,但是问题是它们是否可以从外部获得。如果开发人员不以任何方式提供cli选项或API,则破解代码将是完全不同的工作。我很乐意有选择。
雅各布·弗利姆

1
@JacobVlijm公平点。可能在这里有更多信息stackoverflow.com/questions/18595951/…但是远远超出我的能力水平!
jymbob

1

Open Broadcaster是一种看似过分但完全可以达到目的的工具。在“源”列表框中,单击加号,选择“窗口捕获”,然后按照提示选择您感兴趣的窗口。只需使用预览。它几乎可用于任何操作系统此处有关于Ubuntu的说明,我已在下面进行了复制。

sudo apt-get install ffmpeg
sudo add-apt-repository ppa:obsproject/obs-studio
sudo apt-get update
sudo apt-get install obs-studio

如果您愿意,可以进入“查看”菜单并隐藏所有UI元素。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.