有没有办法存储当前的桌面布局?

有没有办法存储当前的桌面布局?

我希望能够保存我的应用程序的当前位置,因此当我打开相同的应用程序并运行某些程序时,它们将按原来的方式重新排列。

例如如果我要打开一个 Sublime 和三个终端窗口,我希望能够以某种方式保存它。

在此处输入图片描述

我不在乎它是一个应用程序还是一个命令行工具,只要我可以轻松保存我的应用程序的位置。

我非常喜欢穆姆,但不幸的是它只适用于 MacOS,我在 Ubuntu 上真的很想念它。它支持更多功能,如果你知道一些与我的主要问题相关的功能,那也很好。

答案1

笔记

该脚本于 2017 年 1 月 16 日进行了修补/修复,修复了几个应用程序,其中进程名称不同于运行应用程序的命令。可能,这种情况偶尔会在应用程序中发生。如果有人发现,请发表评论。


脚本用于记住并恢复窗口排列及其对应的应用程序。

下面的脚本可以用两个选项运行。假设您的窗口排列如下:

在此处输入图片描述

(记住)当前窗口排列及其应用程序,使用以下选项运行脚本:

<script> -read

然后关闭所有窗口:

在此处输入图片描述

然后设置最后记住的窗口排列,使用以下选项运行它:

<script> -run

并且最后记住的窗口排列将被恢复:

在此处输入图片描述

重启后此操作也将有效。

将这两个命令放在两个不同的快捷键下,您可以“记录”您的窗口排列,关闭您的计算机并在重新启动后调用相同的窗口排列。

脚本的作用以及它的作用不是

使用选项运行-read

  • 该脚本用于wmctrl列出所有工作区中的所有窗口、它们的位置、它们的大小以及它们所属的应用程序
  • 然后,脚本将窗口位置从相对(相对于当前工作区,如 的输出所示wmctrl)“转换”为绝对位置,在您的跨工作区上。因此,无论您要记住的窗口是只在一个工作区上还是分布在不同的工作区上,都没有关系。
  • 然后,脚本会“记住”当前窗口的排列,并将其写入主目录中不可见的文件中。

使用选项运行-run

  • 脚本读取最后记住的窗口排列;它启动相应的应用程序,将窗口移动到记住的位置,同时借助wmctrl

脚本确实不是记住可能在窗口中打开的文件,也不会记住在浏览器窗口中打开的网站(例如)。

问题

wmctrl和的组合Unity存在一些错误,举几个例子:

  • 窗口坐标,读取的wmctrl命令与位置如上所述,窗户这里。因此调用的窗口位置可能与原始位置略有不同。
  • wmctrl如果窗口的边缘非常靠近或Unity Launcher面板,命令的工作会有点不可预测。
  • wmctrl为了使放置命令正常工作,“记住的”窗口需要完全位于工作区边界内。

有些应用程序默认在新选项卡中的同一窗口中打开新窗口(例如gedit)。我已为 修复了此问题gedit,但如果您发现更多例外情况,请告知我们。

剧本

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

如何设置

开始之前,请确保wmctrl已安装:

sudo apt-get install wmctrl

然后:

  1. 将脚本复制到一个空文件中,将其保存为recall_windows~/bin如有必要,请创建目录。如果目录尚不存在,请source ~/.profile在创建目录后运行或注销/登录。它现在将位于$PATH
  2. 使脚本可执行(!)。
  3. 现在打开几个窗口geditfirefox其他任何窗口,然后通过运行命令(不需要路径前缀)在终端中测试运行脚本:

    recall_windows -read
    
  4. 关闭窗口。现在在终端中运行:

    recall_windows -run
    

您的窗口设置现在应该恢复

如果一切正常,请将两个命令添加到快捷键:选择:系统设置>“键盘”>“快捷键”>“自定义快捷键”。单击“+”并添加命令:

recall_windows -read

recall_windows -run

两个不同的快捷键

答案2

我编写了一个小库/命令行工具,它允许保存和恢复会话,并支持不同的显示器设置以及虚拟桌面。

安装

npm install -g linux-window-session-manager

用法

将当前会话保存到 ~/.lwsm/sessionData/DEFAULT.json

lwsm save

将当前会话保存到 ~/.lwsm/sessionData/my-session.json

lwsm save my-session   

从 ~/.lwsm/sessionData/DEFAULT.json 恢复会话

lwsm restore

从 ~/.lwsm/sessionData/my-session.json 恢复会话

lwsm restore my-session   

在开始会话之前妥善关闭所有正在运行的应用程序

lwsm restore --closeAllOpenWindows

一探究竟:https://github.com/johannesjo/linux-window-session-manager

答案3

没有这样的程序。您可以安装 compiz cub:

sudo apt-get install compiz compizconfig-settings-manager compiz-fusion-plugins-extra compiz-fusion-plugins-main compiz-plugins

并关注本指南

compiz 是 unity/gnome 最先进的桌面工具

答案4

我无法将顶部答案中的更新脚本作为评论发布。这是该脚本的略微更新版本。主要变化是,如果应用程序存在,它将被重新定位而不是重新启动。除此之外,这是一个很棒的脚本。我在 Lubuntu 16.04 上使用了它,现在在 18.04 上也使用了它。感谢您编写它。
我已将此脚本发布在我的 github 存储库中: https://github.com/xwin/savelayout
添加了校准功能,其中工具将自动找到偏移量以使恢复的窗口保持在同一位置。

相关内容