Czy mogę wyświetlić okno z małym podglądem na żywo innego obszaru roboczego?


29

Czy można wykonać kopię lustrzaną aktywnej sekcji jednego obszaru roboczego, aby był widoczny w bieżącym obszarze roboczym jako okno, które można przesuwać?

Innego dnia miałem maszynę wirtualną z systemem Windows 10 uruchomioną na moim hoście Ubuntu 16.04, której ukończenie aktualizacji zajęło naprawdę dużo czasu. Sprawdzałem jego postępy za pośrednictwem Expo ( Super+ S) na Ubuntu. To sprawiło, że pomyślałem, że ten problem został najprawdopodobniej już rozwiązany, ponieważ narzędzia takie jak simplescreenrecorder można skonfigurować do nagrywania tylko części ekranu. Nie znam jednak właściwej terminologii używanej do wyszukiwania Google.

Chciałbym zobaczyć zrzut ekranu 300 x 150 poniżej w postaci ruchomego okna (z aktualizacjami na żywo) w prawym górnym rogu dowolnego obszaru roboczego, który stanie się aktualny.

wprowadź opis zdjęcia tutaj


1
@serg tutaj nowy projekt dla Ciebie
Rinzwind

@Rinzwind, musisz nienawidzić Serga ... Oboje już wcześniej patrzyliśmy na coś takiego, ale nam się nie udało.
Jacob Vlijm,

1
Tym razem nawet naliczyłem nagrodę: =) dostań się @JacobVlijm
Rinzwind

Byłaby fajna funkcja :) Nie pomoże w przypadku VM, ale istnieje rozwiązanie dla aplikacji terminalowych: za pomocą Konsoli. Ma dwie przydatne opcje: „powiadom o aktywności” i „powiadom o ciszy”. Pierwszy wyśle ​​Ci powiadomienie, gdy w terminalu pojawi się nowa linia (przydatne, gdy używasz tail -F file | grep patterndzienników do ostrzegania o niektórych zdarzeniach), drugi wyśle ​​Ci powiadomienie, gdy minie trochę czasu od ostatniego napisanego wiersza (przydatne do wiedzieć, kiedy zakończy się kompilacja).
kik

@ Rinzwind, cholera, to zadziała ...
Jacob Vlijm,

Odpowiedzi:


26

EDYTOWAĆ

(Nowa odpowiedź)

GOTOWY.
Poniższa odpowiedź jest teraz dostępna w dopracowanej formie, jako wskaźnik, jako ppa dla programów Trusty, Xenial, Yakkety i Zesty:

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

Wskaźnik Th (łącznie z oknem podglądu) ma teraz całkiem niski poziom soku. Opcje obejmują okno ustawień, ustawienie rozmiaru / koloru obramowania okna, rozmiar okna.

wprowadź opis zdjęcia tutaj

Tymczasem uważam, że warto mieć oko na okno AU; sprawdź, czy są jakieś wiadomości :)


STARA ODPOWIEDŹ

( pierwsza szorstka koncepcja)

Miej zminimalizowaną reprezentację okna w innym obszarze roboczym

Ku memu (wielkiemu) zaskoczeniu można to skutecznie zrobić, czy to podstępem i oszustwem; mają zaktualizowaną reprezentację okna w innym obszarze roboczym. Nie nadaje się do oglądania filmu, zdecydowanie wystarczająco dobry, aby mieć oko na okno w innym miejscu (przykład: moje okno karty telewizyjnej):

Jak to działa w praktyce

  1. W oknie z przodu naciśnij klawisz skrótu:

    wprowadź opis zdjęcia tutaj

    (okno zminimalizuje)

  2. Przejdź do innego obszaru roboczego, naciśnij ponownie klawisz skrótu, pojawi się mała reprezentacja okna, aktualizowana co 4 sekundy:

    wprowadź opis zdjęcia tutaj

    Okno zawsze wyświetla się nad innymi oknami. W tej chwili okno ma 300 pikseli (szerokość), ale można ustawić dowolny rozmiar.

  3. Aby zakończyć, naciśnij (ponownie) klawisz skrótu. Małe okno się zamknie, przejdziesz do okienka oryginalnego okna, które pojawi się ponownie, nie zminimalizowane.

Skrypty

  1. Skrypt sterujący

    #!/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. Reprezentacja okna

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

Jak używać

  1. Zainstalować python3-pil, xdotooliwmctrl

    sudo apt-get install xdotool wmctrl python3-pil
    
  2. Utwórz, jeśli jeszcze nie istnieje, katalog ~/bin.

  3. Skopiuj skrypt 1, kontroluje skrypt jako (dokładnie) showcase_control(bez rozszerzenia) ~/bini sprawia, że ​​jest wykonywalny .
  4. Skopiuj skrypt 2, skrypt mini-okna, jako (dokładnie) showmin(bez rozszerzenia) ~/bini uczyń go wykonywalnym .
  5. Wyloguj się i zaloguj ponownie, a następnie dodaj następujące polecenie do wybranego skrótu:

    showcase_control
    

    Wybierz: Ustawienia systemu> „Klawiatura”> „Skróty”> „Skróty niestandardowe”. Kliknij „+” i dodaj polecenie:

    showcase_control
    

    i powinno działać!

    • Naciśnij klawisz jeden raz, aby chwycić bieżące okno
    • przejdź do innego obszaru roboczego, w którym chcesz mini-okno
    • Naciśnij ponownie, aby wyświetlić miniwindow
    • Naciśnij ponownie, aby wrócić do pierwotnego obszaru roboczego, (automatycznie) cofnij minimalizację oryginalnego okna i zamknij mini-jeden.

Wady?

  • Obecna konfiguracja dodaje trochę pracy procesorowi. Jednak w moim (bardzo) starym systemie dodaje (średnio) ok. 4-5% liczę, czego w żaden sposób nie zauważyłem .

    Aktualizacja: Okazuje się, że importmożna zmienić rozmiar obrazu w jednym kroku, wraz z pobraniem obrazu okna. Oznacza to znaczne zmniejszenie obciążenia procesora. Jednocześnie czas odświeżania jest krótszy (teraz 3 sekundy), wciąż przy niższych „kosztach”.

Wyjaśnienie

  • Moim punktem wyjścia był sposób, w jaki OP wspomniał, że chciał skorzystać z tej opcji, aby mieć oko na okno w innym obszarze roboczym, czekając, aż coś się zakończy.
  • Choć dosłownie posiadające dokładną (mini) kopiowanie z okna na innym obszarze roboczym wydaje się niemożliwe, że można zrobić obraz istniejącego okna z import-polecenie, gdy mamy ID okna. Chociaż działa to zarówno na zminimalizowane okna lub okna bez fokusu, jest jednak jeden problem: okno musi znajdować się w bieżącym obszarze roboczym .
  • Sztuczka polega na tym, aby tymczasowo (podczas korzystania z mini-okna) sprawić, by okno było „lepkie” (być praktycznie dostępne na wszystkich obszarach roboczych) wmctrl, ale jednocześnie zminimalizowane.
  • Ponieważ wszystko odbywa się automatycznie, różnica faktycznie nie występuje, ponieważ powrót do początkowej rzutni, „od-” przyklejenia oryginalnego okna i minimalizowanie go, odbywa się automatycznie.

W skrócie:

  1. Jednokrotne naciśnięcie skrótu: okno docelowe jest lepkie, ale zminimalizowane
  2. Ponowne naciśnięcie (prawdopodobnie w innym obszarze roboczym): w lewym górnym rogu pojawia się mała mini-wersja okna, aktualizowana raz na cztery sekundy.
  3. Ponowne naciśnięcie: mini okno zostanie zamknięte, pulpit przejdzie do początkowej przestrzeni roboczej okna, okno zostanie przywrócone nieprzylepne i zminimalizowane.

Specjalnie dla VirtualBox

Kiedy okno VBox jest z przodu, okazuje się, że klawisze skrótów Ubuntu są wyłączone (!), Więc skrypt sterujący musi zostać uruchomiony w inny sposób. Poniżej kilka krótkich.

opcja 1

Zredagowałem skrypt sterujący. Teraz tylko w przypadku VirtualBox:

  • Kliknij dowolne miejsce na pulpicie, a następnie naciśnij klawisz skrótu. Następnie wystarczy użyć klawisza skrótu, aby wyświetlić okno i wyjść.

    Objaśnienie: Skrypt sterujący został zamknięty, jeśli okno było typu „pulpit”, ponieważ nie chcesz minimalizować pulpitu. Teraz skrypt najpierw szuka możliwych istniejących okien VirtualBox, aby celować, jeśli aktualnie aktywnym oknem jest pulpit.

Opcja 2

  • Skopiuj ikonę poniżej (kliknij prawym przyciskiem myszy -> zapisz jako), zapisz jako minwinicon.png

    wprowadź opis zdjęcia tutaj

  • Skopiuj poniższe linie do pustego pliku, zapisać go jako minwin.desktopw ~/.local/share/applications:

    [Desktop Entry]
    Type=Application
    Name=Window Spy
    Exec=showcase_control 
    Icon=/path/to/minwinicon.png
    StartupNotify=false
    

    Musisz się wylogować i ponownie zalogować, aby program uruchamiający „znalazł” ~/binścieżkę lokalną !
    Przeciągnij ikonę na program uruchamiający, aby go użyć.

Drugie rozwiązanie ma ważną wadę: po użyciu go z programu uruchamiającego będzie mrugać przez kilka sekund, czekając na pojawienie się okna. W tym czasie kliknięcie ponownie nie przyniesie żadnego efektu. Które mogą być rozwiązane, jak opisano tutaj , ale w tym, że w tej odpowiedzi będzie naprawdę sprawiają, że zbyt długo. Jeśli chcesz skorzystać z opcji drugiej, sprawdź link.


Stary dobry importmoże to zrobić, a zrzut ekranu gnome nie. Bardzo, bardzo interesujące. Jestem ciekawa, jaka dokładnie jest różnica między sposobem, w jaki działają
Sergiy Kolodyazhnyy,

@Serg tak, byłem naprawdę zaskoczony, pomyślałem, że nie da się tego zrobić za pomocą samych narzędzi kuchennych :)
Jacob Vlijm,

1
@ThatGuy nad nim pracuje :)
Jacob Vlijm

1
@jymbob Dzięki za komentarz! Nie mają wątpliwości w systemie, ale pytanie brzmi, czy są dostępne z zewnątrz. Jeśli programiści nie udostępniają opcji cli ani interfejsu API w jakikolwiek sposób, włamanie się do kodu byłoby zadaniem o zupełnie innej kolejności. Chciałbym jednak mieć taką opcję.
Jacob Vlijm

1
@JobobVlijm Fair point. Prawdopodobnie więcej informacji tutaj stackoverflow.com/questions/18595951/... ale znacznie powyżej moich kompetencji!
jymbob

1

Coś, co wydaje się przesadą, ale całkowicie działa w tym celu, to Open Broadcaster . W polu listy „Źródła” kliknij plus, wybierz „Przechwytywanie okna”, a następnie postępuj zgodnie z instrukcjami, aby wybrać okno, które Cię interesuje. Nie ma sensu bić rekordu; po prostu użyj podglądu. Jest dostępny na prawie każdym systemie operacyjnym , z instrukcjami dla Ubuntu tutaj , które skopiowałem poniżej.

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

Jeśli masz na to ochotę, możesz przejść do menu „Widok” i ukryć wszystkie elementy interfejsu użytkownika.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.