Hinweis
Das Skript wurde am 16. Januar 2017 gepatcht / repariert, und zwar für einige Anwendungen, deren Prozessname vom Befehl zum Ausführen der Anwendung abweicht . Möglicherweise tritt dies gelegentlich bei Anwendungen auf. Wenn jemand einen findet, hinterlasse bitte einen Kommentar.
Skript zum Speichern und Wiederherstellen der Fensteranordnung und der entsprechenden Anwendungen.
Das folgende Skript kann mit zwei Optionen ausgeführt werden. Angenommen, Sie haben die Fensteranordnung wie folgt:
Führen Sie das Skript mit der folgenden Option aus, um die aktuelle Fensteranordnung und ihre Anwendungen zu lesen (zu speichern):
<script> -read
Dann schließen Sie alle Fenster:
Führen Sie dann zum Einrichten der zuletzt gespeicherten Fensteranordnung die folgende Option aus:
<script> -run
und die zuletzt gespeicherte Fensteranordnung wird wiederhergestellt:
Dies funktioniert auch nach einem Neustart.
Wenn Sie die beiden Befehle unter zwei verschiedenen Tastenkombinationen platzieren, können Sie Ihre Fensteranordnung "aufzeichnen", Ihren Computer herunterfahren und nach (z. B.) einem Neustart dieselbe Fensteranordnung aufrufen.
Was das Skript macht und was nicht
Mit der Option ausführen -read
- Das Skript
wmctrl
listet alle Fenster auf, über alle Arbeitsbereiche hinweg, ihre Positionen, ihre Größen und die Anwendungen, zu denen sie gehören
- Das Skript "konvertiert" dann die Fensterpositionen von relativen (zum aktuellen Arbeitsbereich, wie in der Ausgabe von
wmctrl
) zu absoluten Positionen in Ihren übergreifenden Arbeitsbereichen. Daher spielt es keine Rolle, ob sich die Fenster, an die Sie sich erinnern möchten, nur in einem Arbeitsbereich befinden oder auf verschiedene Arbeitsbereiche verteilt sind.
- Das Skript "merkt" sich dann die aktuelle Fensteranordnung und schreibt sie in eine unsichtbare Datei in Ihrem Home-Verzeichnis.
Mit der Option ausführen -run
- das Skript liest die zuletzt gespeicherte Fensteranordnung; es startet die entsprechenden anwendungen, verschiebt die fenster an die gespeicherten positionen, auch mit hilfe von
wmctrl
Das Skript speichert weder die Dateien, die möglicherweise in den Fenstern geöffnet wurden, noch (z. B.) die Websites, die in einem Browserfenster geöffnet wurden.
Probleme
Die Kombination von wmctrl
und Unity
hat einige Bugs, ein paar Beispiele:
- Die von gelesenen Fensterkoordinaten
wmctrl
unterscheiden sich geringfügig vom Befehl zum Positionieren der Fenster, wie hier erwähnt . Daher können die abgerufenen Fensterpositionen geringfügig von der ursprünglichen Position abweichen.
- Die
wmctrl
Befehle funktionieren etwas unvorhersehbar, wenn sich der Rand des Fensters sehr nahe am Unity Launcher
oder am Bedienfeld befindet.
- Die "erinnerten" Fenster müssen sich vollständig innerhalb eines Arbeitsbereichs befinden, damit der
wmctrl
Platzierungsbefehl ordnungsgemäß funktioniert.
Einige Anwendungen öffnen neue Fenster standardmäßig im selben Fenster auf einer neuen Registerkarte (z. B. gedit
). Ich habe es für behoben gedit
, aber bitte erwähnen Sie es, wenn Sie weitere Ausnahmen finden.
Das Drehbuch
#!/usr/bin/env python3
import subprocess
import os
import sys
import time
wfile = os.environ["HOME"]+"/.windowlist"
arg = sys.argv[1]
def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")
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
def get_res():
# get resolution and the workspace correction (vector)
xr = subprocess.check_output(["xrandr"]).decode("utf-8").split()
pos = xr.index("current")
res = [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
vp_data = subprocess.check_output(["wmctrl", "-d"]).decode("utf-8").split()
curr_vpdata = [int(n) for n in vp_data[5].split(",")]
return [res, curr_vpdata]
app = lambda pid: subprocess.check_output(["ps", "-p", pid, "-o", "comm="]).decode("utf-8").strip()
def read_windows():
res = get_res()
w_list = [l.split() for l in get("wmctrl -lpG").splitlines()]
relevant = [[w[2],[int(n) for n in w[3:7]]] for w in w_list if check_window(w[0]) == True]
for i, r in enumerate(relevant):
relevant[i] = app(r[0])+" "+str((" ").join([str(n) for n in r[1]]))
with open(wfile, "wt") as out:
for l in relevant:
out.write(l+"\n")
def open_appwindow(app, x, y, w, h):
ws1 = get("wmctrl -lp"); t = 0
# fix command for certain apps that open in new tab by default
if app == "gedit":
option = " --new-window"
else:
option = ""
# fix command if process name and command to run are different
if "gnome-terminal" in app:
app = "gnome-terminal"
elif "chrome" in app:
app = "/usr/bin/google-chrome-stable"
subprocess.Popen(["/bin/bash", "-c", app+option])
# fix exception for Chrome (command = google-chrome-stable, but processname = chrome)
app = "chrome" if "chrome" in app else app
while t < 30:
ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
if app in p and w[2] in p] for w in ws2]
if len(procs) > 0:
time.sleep(0.5)
w_id = procs[0][0][1]
cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
cmd3 = "wmctrl -ir "+procs[0][0][1]+" -e 0,"+x+","+y+","+w+","+h
for cmd in [cmd1, cmd2, cmd3]:
subprocess.call(["/bin/bash", "-c", cmd])
break
time.sleep(0.5)
t = t+1
def run_remembered():
res = get_res()[1]
try:
lines = [l.split() for l in open(wfile).read().splitlines()]
for l in lines:
l[1] = str(int(l[1]) - res[0]); l[2] = str(int(l[2]) - res[1] - 24)
open_appwindow(l[0], l[1], l[2], l[3], l[4])
except FileNotFoundError:
pass
if arg == "-run":
run_remembered()
elif arg == "-read":
read_windows()
Wie stellt man das ein
Bevor Sie beginnen, stellen Sie sicher, dass Folgendes wmctrl
installiert ist:
sudo apt-get install wmctrl
Dann:
- Kopieren Sie das Skript in eine leere Datei, speichern Sie es als
recall_windows
in ~/bin
. Erstellen Sie ggf. das Verzeichnis. Wenn das Verzeichnis noch nicht existiert hat, führen Sie entweder aus source ~/.profile
oder melden Sie sich ab, nachdem Sie das Verzeichnis erstellt haben. Es wird jetzt in sein$PATH
- Machen Sie das Skript ausführbar (!).
Öffnen Sie nun ein paar Fenster, gedit
, firefox
oder was auch immer, und das Skript in einem Terminal - Testlauf mit dem Befehl ausgeführt wird (kein Pfadpräfix erforderlich):
recall_windows -read
Schließe die Fenster. Jetzt in einem Terminal ausführen:
recall_windows -run
Ihr Fenster-Setup sollte jetzt wiederhergestellt sein
Wenn alles funktioniert, fügen Sie den Tastenkombinationen zwei Befehle hinzu: Wählen Sie: Systemeinstellungen> "Tastatur"> "Tastenkombinationen"> "Benutzerdefinierte Tastenkombinationen". Klicken Sie auf das "+" und fügen Sie die Befehle hinzu:
recall_windows -read
und
recall_windows -run
auf zwei verschiedene Tastenkombinationen