summaryrefslogtreecommitdiff
path: root/README.md
blob: 997b0f6dfd085132191f566ec6e75006ffa29c21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# About Summoner

This is a daemon script, that manages summoning layouts.
By summoning layouts, I mean, showing set of floating windows on top of your workspace windows in floating mode.


You don't need to know python and be deeply into programming to configure and use Summoner, but it is still just a script and i don't plan to support any external configs.

It's features:

1. Summon layout on empty workspaces on workspace switch
2. Summon layouts with keybindings
3. Spawn processes to use for layouts
4. Or use already running windows as parts of the layout
5. Restore window position after using this window in layout summon
6. Support multihead setups


# Running
#### It is not standalone package
For now, it is not a package, and you'll need to manage dependencies on your own. Summoner has only one dependecny - i3ipc.
You can either run
```bash
. ./setup.sh
```
or
```bash
python -m venv venv
. ./venv/bin/activate
pip install -r req.txt
```

To run script, you'll need your envrinment activated. You can either do:
```bash
. ./run.sh
```
or
```bash
. ./venv/bin/activate
python summoner.py
```

Tho, you'll probably want to run it inside of i3 config. After placing summoner into the `.config/i3/summoner`:

```bash
exec_always --no-startup-id ~/.config/i3/summoner/run.sh
```


# Configuration
## Simply showing windows on empty workspaces
If you want to use Summoner only to summon layout on empty workspace, you only need to setup your initial layout.
Open script and find `LAYOUTS` variable.
Edit it to be something like this:


```python
LAYOUTS = {
    '############': Layout(
        windows=[
            Window(
                run=["alacritty", "-T", "cmatrix1", "-e", "cmatrix"],
                geometry={"x": 350, "y": 150, "w": 250, "h": 500},
                window_name="cmatrix1",
            ),
            Window(
                run=None,
                geometry={"x": 900, "y": 300, "w": 250, "h": 500},
                window_name="cmatrix2",
                workspace="1"
                skip_spawn=True,
                skip_init=True,
                steal_focus=True,
            ),
        ]
    ),
```
|---|---|
|`run`|  Either None (explicitly) or list of cli args to run |
| `geometry` |  dict in format {"x": 0, "y": 0, "w": 0, "h": 0}, where `x`, `y` is top left of your workspace (output) `w` is window width and `h` is window height. Note that window should be at least 100/100 in size, or window will be counted as too small and not displayed (it still will be spawned) |
| `window_name` | name of the window. Note that it should be unique, and you need to either set it in `run` somewhere, depending on what you run, or by hand, when you run with `skip_spawn` |
| `workspace` | home workspace window will hide itself at. Default as "w_hidden" |
| `skip_spawn` | skipping spawn step of setup. This means you started your process yourself, or plan to start it later |
| `skip_init` | skipping init step of setup. This means, you don't touch window (don't store it's initial values, don't float it, don't resize, don't move it to hidden workspace, etc) |
| `steal_focus` | make this window steal focus from whatever focus was beforehand |
| `restore_to_initial_state` | record initial state of window (init step, don't skip it). When window should be hided, it will try to go to it's initial state. Note that it does not save any layout data, only simple workspace/floated/focused |


## Summoning windows with key presses
If you want to bring out full potential of Summoner and make it summon floating windows right in your face, on top of your current tiling layout, you need to do as follows:

### Edit i3 config
Unfortunately, you need to edit i3 config for it to work. You need to bind some keystrokes for Summoner to catch. Hopefully, it is pretty easy to do.
Just add string like this in your config:
```bash
bindsym --release $mod+Ctrl+y exec --no-startup-id  echo "show_system_monitor"
```

In the i3, whole exec line, including exec will be caught as binding:
```bash
exec --no-startup-id  echo "show_system_monitor"
```

### Edit Summoner

Now, we'll need to edit script file itself. Notice how we had bunch of hashes as the key for `LAYOUTS` in the first example. It was like this because it did not really mattered what value we put there, it will still work. You can even put `ur_mom` in here, but i will be carefull not to cause buffer overflow.
Anyway, now, key for the `LAYOUTS` dictionary will play it's role.

We need to set key to our binded command, including exec and everything after. Like this:
```python
LAYOUTS = {
    'exec --no-startup-id  echo "show_system_monitor"': Layout(
        windows=[
            ...
        ],
    ),
}

```

And, we will need to setup, how our layout is closed:
```python
LAYOUTS = {
    'exec --no-startup-id  echo "show_system_monitor"': Layout(
        ...,
        close_layout_on=[
            'exec --no-startup-id  echo "show_system_monitor"',
        ],            
    ),
}

```

Why this separation?

So we can have scenario like this then:

> .configs/i3/config
```bash
bindsym --release $mod+Ctrl+y exec --no-startup-id  echo "show_system_monitor"
bindsym --release $mod+Ctrl+u exec --no-startup-id  echo "show_newsboat"
bindsym --release $mod+Ctrl+i exec --no-startup-id  echo "show_newsboat_and_system_monitor"

```

> Summoner.py
```python

LAYOUTS = {
    'show_system_monitor': Layout(
        windows=[
            Window(
                run=["system_monitor.sh"],
                ...
            ),
        ],
        close_layout_on=[
            'exec --no-startup-id  echo "show_system_monitor"',
        ]
    ),
    'exec --no-startup-id  echo "show_newsboat"': Layout(
        windows=[
            Window(
                run=["alacritty", "-T", "w_newsboat", "-e", "newsboat"],
                window_name="w_newsboat",
            ),
        ],
        close_layout_on=[
            'exec --no-startup-id  echo "show_system_monitor"',
            'exec --no-startup-id  echo "show_newsboat"',
        ]
    ),
    'exec --no-startup-id  echo "show_newsboat_and_system_monitor"': Layout(
        windows=[
            Window(
                run=["alacritty", "-T", "w_newsboat", "-e", "newsboat"],
                window_name="w_newsboat",
            ),
        ],
        close_layout_on=[
            'exec --no-startup-id  echo "show_newsboat_and_system_monitor"',
        ]
    ),
}

```

In this case, if we hit firts key combination (mod+ctrl+y) will bring out system_monitor, then, if we hit second combination (mod+ctrl+u), we will summon newsboat. Otherwise, we would first close system monitor, and only after this we will be able to bring out system_monitor.
Then, inside of "newsboat" layout, we can close whole layout either hitting system_monitor combination, or newsboat combination
And, after navigating into the show_newsboat_and_system_monitor (mod+ctrl+i), we will be able to close this layout only with show_newsboat_and_system_monitor combination.
Hitting system_monitor or newsboat combinations (mod+ctrl+y/mod+ctrl+u), we will not close whole overlay, but navigate back to each layout respectfully.

So, this system, gives as ability to do some simple "navigation" between layouts, saving some keystrokes, and sanity.


## Restorable windows
As you couldve seen, `Window` have `restore_to_initial_state`. It makes it possible (while still very crude) to bring window back, from where it was taken to show on the layouts.
Initially, this feature was intended to be used shile streaming, to summon chat on screen, from secondary monitor, to the main one, which is captured by obs, and then brought back.
Hope it will be usable with any other usecases.


## Multihead
Summoner supports multihead (tho, only tested in 2 monitor setup by me). General behaviour of summoned layouts will be the same as in the single monitor setup, but in case one of the monitor workspaces considered "empty", when you move focus form "empty" monitor, to monitor with windows opened, current layout will "stick" to the empty monitor (otherwise it wouldve just hid itself)



# Contribution
This repo does not accepts contributions outright. If you want to contribute, hit me up on discord (@myortv) or email (myortv@proton.me) (email is worse, i rarely check it) and i'll either merge your patches or give you access to git ssh.
If you found any bugs, hit me up on discord (@myortv) or email (myortv@proton.me)
If you have any feature requests, hit me up on discord (@myortv) or email (myortv@proton.me)
If you are hop femboy in my area, hit me up on discord (@myortv) or email (myortv@proton.me)