Skip to content
This repository was archived by the owner on Dec 26, 2023. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico Rittstieg committed Dec 21, 2018
1 parent 8467ff4 commit 15e3380
Show file tree
Hide file tree
Showing 9 changed files with 517 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ venv.bak/

# mypy
.mypy_cache/

# IntelliJ
.idea
*.iml
90 changes: 88 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,88 @@
# savedesktop
CLI tool for saving and restoring virtual linux desktops
# SaveDesktop

A CLI tool for saving and restoring virtual linux desktops.

Currently in proof of concept.

Main features:
-------------------
- Dumping window geometry and hints to human readable JSON files
- Apply the saved layout to any virtual desktop
- Command Line Interface

Dependencies:
----------------------

- X Window Manager that implement the EWMH specification
- wmctrl (https://sites.google.com/site/tstyblo/wmctrl/)
- xwininfo
- Python 3
- python-setuptools

Installation:
--------------------------

Arch Linux package:

```
$ pacman -U savedesktop-*.pkg.tar.xz
```

For manual installation use the following command:

```
$ sudo python setup.py install --optimize=1
```

Usage:
--------------------------

dump a desktop:

```
$ sd -d 0 -p profile1 -o
```
options:

`-d 0` dump first desktop

`-p profile1` save to ~/.config/savedesktop/profile1.json

`-o` open in default editor

restore a desktop:

```
$ rd -d 1 -p profile1
```

`-d 1` restore to second desktop

`-p profile1` load ~/.config/savedesktop/profile1.json

Project Web site :
--------------------

https://github.com/nrittsti/savedesktop/

--------------------------------------------------------------------------------
Licence:
--------------------------------------------------------------------------------


This program is free software:
you can redistribute it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.
If not, see <http://www.gnu.org/licenses/>.

Copyright (C) 2018 Nico Rittstieg

--------------------------------------------------------------------------------
End of document
24 changes: 24 additions & 0 deletions read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# This file is part of savedesktop.
# A CLI tool for saving and restoring virtual linux desktops.
#
# Copyright (C) 2018 Nico Rittstieg
#
# This program is free software:
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <http://www.gnu.org/licenses/>.

import savedesktop.rd as rd

if __name__ == '__main__':
rd.main()
24 changes: 24 additions & 0 deletions save.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# This file is part of savedesktop.
# A CLI tool for saving and restoring virtual linux desktops.
#
# Copyright (C) 2018 Nico Rittstieg
#
# This program is free software:
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <http://www.gnu.org/licenses/>.

import savedesktop.sd as sd

if __name__ == '__main__':
sd.main()
19 changes: 19 additions & 0 deletions savedesktop/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# This file is part of savedesktop.
# A CLI tool for saving and restoring virtual linux desktops.
#
# Copyright (C) 2018 Nico Rittstieg
#
# This program is free software:
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <http://www.gnu.org/licenses/>.
81 changes: 81 additions & 0 deletions savedesktop/rd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# This file is part of savedesktop.
# A CLI tool for saving and restoring virtual linux desktops.
#
# Copyright (C) 2018 Nico Rittstieg
#
# This program is free software:
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <http://www.gnu.org/licenses/>.

import argparse
import json
import subprocess
import sys
import time
from pathlib import Path
from typing import List

import savedesktop.wmctrl as wmctrl


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--profile", default="default", help="profile name")
parser.add_argument("-d", "--desktop", type=int, default=0, help="target desktop number from 0 to n")
parser.add_argument("--version", action="version", version="0.01")
args = parser.parse_args()
window_list = list()
try:
window_list = read_profile(args.profile)
except FileNotFoundError as e:
print("profile '{0}' not found".format(e.filename), file=sys.stderr)
exit(-1)
try:
if not wmctrl.check_wmctrl_installation():
print("wmctrl is not installed", file=sys.stderr)
exit(-1)
wmctrl.switch_desktop(args.desktop)
for props in window_list:
open_window(args.desktop, props)
except subprocess.CalledProcessError as e:
print("wmctrl did not work properly: {0}".format(str(e)), file=sys.stderr)
exit(-1)


def read_profile(profile: str) -> List[dict]:
json_path = Path.home().joinpath(".config/savedesktop/" + profile + ".json")
text = json_path.read_text("UTF-8")
result = json.loads(text)
return result


def open_window(desktop: int, props: dict) -> bool:
window_ids = wmctrl.list_window_id(desktop)
print(window_ids)
subprocess.Popen(props["cmd"], shell=False)
for x in range(10):
time.sleep(.50)
new_ids = wmctrl.list_window_id(desktop) - window_ids
if len(new_ids) == 0:
continue
win_id = new_ids.pop()
wmctrl.resize_move(win_id, props["x"], props["y"], props["width"], props["height"])
if len(props["state"]) > 0:
wmctrl.set_state(win_id, props["state"])
return True
return False


if __name__ == "__main__":
main()
75 changes: 75 additions & 0 deletions savedesktop/sd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# This file is part of savedesktop.
# A CLI tool for saving and restoring virtual linux desktops.
#
# Copyright (C) 2018 Nico Rittstieg
#
# This program is free software:
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <http://www.gnu.org/licenses/>.

import argparse
import json
import subprocess
import sys
from pathlib import Path
from typing import List

import savedesktop.wmctrl as wmctrl


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-o", "--open", action="store_true", help="open saved profile")
parser.add_argument("-p", "--profile", default="default", help="custom profile name")
parser.add_argument("-d", "--desktop", type=int, default=None, help="desktop number from 0 to n")
parser.add_argument("--version", action="version", version="0.01")
args = parser.parse_args()
try:
if not wmctrl.check_wmctrl_installation():
print("wmctrl is not installed", file=sys.stderr)
exit(-1)
if not wmctrl.check_xwininfo_installation():
print("xwininfo is not installed", file=sys.stderr)
exit(-1)
if args.desktop is not None:
desktop = args.desktop
else:
desktop = wmctrl.current_desktop()
window_list = wmctrl.list_window_details(desktop)
json_path = write_profile(window_list, args.profile)
if args.open:
subprocess.call(["xdg-open", str(json_path)])

except subprocess.CalledProcessError as e:
print("wmctrl did not work properly: {0}".format(str(e)), file=sys.stderr)
exit(-1)


def write_profile(window_list: List[dict], profile: str) -> Path:
# remove unnecessary window properties
for props in window_list:
del props["id"]
del props["desktop"]
del props["pid"]

text = json.dumps(window_list, indent=2)
conf_dir = Path.home().joinpath(".config/savedesktop")
conf_dir.mkdir(exist_ok=True)
json_path = conf_dir.joinpath(profile + ".json")
json_path.write_text(text, "UTF-8")
return json_path


if __name__ == "__main__":
main()
Loading

0 comments on commit 15e3380

Please sign in to comment.