Every morning I have to open, resize and reposition all applications I need to work, so I thought: What if I only had to press a keyboard shortcut that could do that for me...
To make this happen I would need to write a script that will be executed by that shortcut, this script would have to do three tasks: Open applications, wait for it to start, and resize and reposition them.
Before continuing, this was developed and tested on Pop!_OS 20.04 LTS, a Ubuntu-based Linux distro. The source code is here. I could just use suspend mode, but I use dual boot, so that doesn't always work for me, and exploring other tools to find a solution is way more fun.
This script was written in Python 3.8, I called it desktop-bootstrap.py, to open the applications I used the subprocess module. And to resize and reposition I used the command line tool wmctrl. The script accepts arguments, so you can open one application at a time, but it also supports a configuration file to open a set of applications, I'll cover in this article the latter approach.
In each line of the configuration file, you write the application you want to open, the command to open it, size and position, like this:
<command> <Application name> <X Axios> <Y Axios> <Window width> <Window height>
An example of a configuration file would be:
insomnia insomnia 960 0 960 1080
google-chrome google 0 0 960 1080 https://dev.to/ricardo93borges https://github.com/ricardo93borges
Note that most browsers accept as arguments the websites to open when it starts, each website open in a different tab, so we'll take advantage of that. You can name the configuration file as config-sample.txt
.
Now we need a shell script that will be executed when we use the keyboard shortcut, this shell script will call the python script passing as an argument the location of the configuration file. I want to open a terminal too, so I also included the command to do so in the shell script:
1# desktop-bootstrap.sh 2 3#!/bin/sh 4gnome-terminal --geometry 170x25+1920+890 --working-directory=/home 5/usr/bin/python3.8 /path/to/desktop-bootstrap.py --file /path/to/config-sample.txt
Here is the python script with comments to explain some pieces of the code:
1# desktop-bootstrap.py
2
3import subprocess
4import time
5import sys
6
7"""
8I limited the retries, so the script doesn't run
9forever waiting for an application to start
10"""
11max_retries = 20
12
13"""
14This method get an application ID looking for its name
15in a list obtained by a wmctrl command,
16that ID is used in the resize command
17"""
18def get_id_by_name(applications_running, name):
19 for app in applications_running:
20 if app.lower().find(name) > -1:
21 return app.split(' ')[0]
22
23"""
24This method receives a list of applications and
25for each one check if is running. If is running resize and
26reposition it, if not check again in the next iteration
27"""
28def resize(applications):
29 retry = 0
30 while len(applications) > 0:
31# Get a list of running applications
32 applications_running = subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").split("\n")
33 for index, app in enumerate(applications):
34 application_id = get_id_by_name(applications_running, app['name'])
35 if application_id:
36# Resize and reposition
37 dimensions = "-e " f"0,{app['x']},{app['y']},{app['width']},{app['height']}"
38 command = ["wmctrl", "-i", "-r", application_id, dimensions]
39 subprocess.run(command)
40 applications.pop(index)
41
42 retry += 1
43 if retry > max_retries:
44 break
45
46 time.sleep(5)
47
48"""
49This method open the application and send it to
50resize() method to resize and reposition it
51accordingly to the arguments passed
52"""
53def handle_args():
54 command = [sys.argv[1]]
55
56"""
57If the application is a browser it may have more
58arguments (the websites to open when it starts)
59"""
60 for i in range(len(sys.argv) - 7):
61 command.append(sys.argv[7 + i])
62
63 output = subprocess.Popen(command)
64
65 applications = [{
66 'name': sys.argv[2],
67 'pid': output.pid,
68 'x': sys.argv[3],
69 'y': sys.argv[4],
70 'width': sys.argv[5],
71 'height': sys.argv[6]
72 }]
73
74 resize(applications)
75
76"""
77This method handles the configuration file, open
78the applications and send it to resize() method
79to resize and reposition it.
80"""
81def handle_file(file):
82 applications = []
83 with open(file) as f:
84 for index, line in enumerate(f):
85 props = line.split(' ')
86 command = [props[0]]
87
88"""
89If the application is a browser it may have
90more arguments (the websites to open when it starts)
91"""
92 for i in range(len(props) - 6):
93 command.append(props[6+i])
94
95 output = subprocess.Popen(command)
96 applications.append({
97 'name': props[1],
98 'pid': output.pid,
99 'x': props[2],
100 'y': props[3],
101 'width': props[4],
102 'height': props[5]
103 })
104 resize(applications)
105
106"""
107Main method, check the arguments and call the
108appropriated method to process the applications.
109"""
110def run():
111 if len(sys.argv) > 2:
112 if sys.argv[1] == "--file":
113 handle_file(sys.argv[2])
114 else:
115 handle_args()
116 else:
117 print("\nInvalid number of arguments")
118 print("\nUse the following arguments: ")
119 print("\n<command> <Application name> <X Axios> <Y Axios> <Window width> <Window height>")
120 print("\nOr: ")
121 print("\n--file <path/to/configuration/file>")
122
123 sys.exit(0)
124
125
126run()
127
Finally, we'll create the keyboard shortcut, this may differ from one Linux distribution to another, in Pop_OS! 20.04 you open settings menu go to keyboard shortcuts, then scroll down to the bottom of the list of shortcuts and click on the + button. In the window that launched you set a name for the shortcut, in the command input you type the path to that shell script (desktop-bootstrap.sh), for example: /home/ricardo/workspace/desktop-bootstrap/desktop-bootstrap.sh
. In shortcut, you choose the combinations of keys that will execute the shell script.
And that's it, you can find more details on this repository.