Skip to content

Commit 6983750

Browse files
committed
Add systray option to "rescue" windows.
I realised that if the user directly applies a layout or a rule, there are no checks for if that rule is valid or not. This means that you can accidentally send windows off-screen, making it really hard to get them back. Previously, you could use `ALT+SPACE M` and use arrow keys to move it, create another rule to move the window back or restore your current snapshot. Now, you can just open the systray menu, click "Rescue windows" and it will find any off-screen windows and move them back to (0, 0) coords
1 parent 52d28e8 commit 6983750

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/main.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from gui import TaskbarIcon, WxApp, about_dialog, radio_menu
1111
from gui.wx_app import spawn_gui
1212
from snapshot import SnapshotFile, SnapshotService
13-
from window import restore_snapshot
13+
from window import apply_positioning, from_hwnd, is_window_valid, restore_snapshot
1414

1515

1616
def update_systray_options():
@@ -41,7 +41,7 @@ def update_systray_options():
4141
if not snapshot.phony:
4242
continue
4343
layout_menu.append([snapshot.phony, lambda *_, s=snapshot: restore_snapshot([], s.rules)])
44-
menu_options[6][1][1:] = layout_menu
44+
menu_options[7][1][1:] = layout_menu
4545

4646
rule_menu = []
4747
for header, ruleset in (
@@ -55,7 +55,7 @@ def update_systray_options():
5555
for rule in ruleset:
5656
rule_menu.append([rule.rule_name or 'Unnamed Rule',
5757
lambda *_, r=rule: restore_snapshot([], [r])])
58-
menu_options[7][1][:-2] = rule_menu
58+
menu_options[8][1][:-2] = rule_menu
5959

6060

6161
def clear_restore_options():
@@ -69,6 +69,20 @@ def clear_restore_options():
6969
snap.clear_history()
7070

7171

72+
def rescue_windows(snap: SnapshotFile):
73+
def callback(hwnd, _):
74+
if not is_window_valid(hwnd):
75+
return
76+
window = from_hwnd(hwnd)
77+
if not window.fits_display_config(displays):
78+
rect = [0, 0, *window.size]
79+
logging.info(f'rescue window {window.name!r} {window.rect} -> {rect}')
80+
apply_positioning(hwnd, rect)
81+
82+
displays = snap.get_current_snapshot().displays
83+
win32gui.EnumWindows(callback, None)
84+
85+
7286
if __name__ == '__main__':
7387
logging.basicConfig(filename=local_path('log.txt'),
7488
filemode='w',
@@ -93,6 +107,7 @@ def clear_restore_options():
93107
TaskbarIcon.SEPARATOR,
94108
['Most recent', lambda *_: snap.restore(-1)]
95109
]],
110+
['Rescue windows', lambda *_: rescue_windows(snap)],
96111
TaskbarIcon.SEPARATOR,
97112
[
98113
'Snapshot frequency', radio_menu(

0 commit comments

Comments
 (0)