Skip to content

Commit a1996f3

Browse files
author
marcelkb
committed
bugfix: thread terminate directly
bugfix: statehandling feature: current status in tray text feature: restart tray icon if explorer restarted
1 parent 9be8530 commit a1996f3

File tree

1 file changed

+71
-23
lines changed

1 file changed

+71
-23
lines changed

keep_awake.py

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import ctypes
2-
import time
32
import datetime
43
import subprocess
54
import threading
5+
66
from loguru import logger
77
import pystray
88
from PIL import Image, ImageDraw
@@ -34,9 +34,10 @@
3434
DISABLE_IF_WORKSTATION_LOCKED = config.get("disable_if_workstation_locked", False)
3535

3636
# --- Sleep control ---
37-
running = True
3837
working = True # whether we keep the PC awake
3938
last_state = None # Track last applied state
39+
stop_event = threading.Event()
40+
worker_thread = None # global
4041

4142
def disable_sleep():
4243
# Run the command
@@ -74,7 +75,7 @@ def enable_sleep():
7475
def keep_awake(icon):
7576
global last_state
7677
logger.info("KeepAwake service started")
77-
while running:
78+
while not stop_event.is_set():
7879
now = datetime.datetime.now()
7980
weekday = now.weekday() # 0=Monday, 6=Sunday
8081

@@ -95,19 +96,26 @@ def keep_awake(icon):
9596
success = enable_sleep()
9697
if success:
9798
last_state = desired_state
99+
update_status(icon)
100+
101+
# optical if its in working time and enabled
102+
if desired_state == "awake" and weekday < 5 and START_HOUR <= now.hour < END_HOUR and icon.icon != ICON_WORKTIME:
103+
icon.icon = ICON_WORKTIME
104+
elif desired_state == "normal" or not (weekday < 5 and START_HOUR <= now.hour < END_HOUR):
105+
icon.icon = ICON_ACTIVE
98106
else:
99-
logger.info("no state change, sleep change call was unsuccessful")
107+
logger.error("no state change, sleep change call was unsuccessful")
100108
else:
101-
logger.info(f"No state change, still '{last_state}'")
109+
logger.info(f"No state change, still '{last_state}' with working: {working} and stop event not set.")
102110

103-
# optical if its in working time and enabled
104-
if desired_state == "awake" and weekday < 5 and START_HOUR <= now.hour < END_HOUR and icon.icon != ICON_WORKTIME:
105-
icon.icon = ICON_WORKTIME
106-
elif desired_state == "normal" or not (weekday < 5 and START_HOUR <= now.hour < END_HOUR):
107-
icon.icon = ICON_ACTIVE
111+
# If icon object exists but tray is gone → restart it
112+
if icon and not icon.visible:
113+
logger.info("Explorer restarted? → restoring tray icon")
114+
restart_icon()
108115

109116
logger.info(f"Sleep {CHECK_INTERVAL}s")
110-
time.sleep(CHECK_INTERVAL) # check every 5 minutes
117+
# Wait, but allow early exit
118+
stop_event.wait(CHECK_INTERVAL)
111119

112120
# --- Icon creation ---
113121
def make_icon(color):
@@ -145,41 +153,65 @@ def is_workstation_locked():
145153
# --- Tray menu actions ---
146154
def on_start(icon, item):
147155
global working
156+
global last_state
148157
working = True
149158
now = datetime.datetime.now()
150159
weekday = now.weekday() # 0=Monday, 6=Sunday
151160
if weekday < 5 and START_HOUR <= now.hour < END_HOUR and icon.icon != ICON_WORKTIME:
152161
icon.icon = ICON_WORKTIME
162+
disable_sleep()
163+
last_state = "awake"
153164
else:
154165
icon.icon = ICON_ACTIVE
155-
166+
enable_sleep()
167+
last_state = "normal"
168+
update_status(icon)
156169
logger.info("KeepAwake activated")
157-
disable_sleep()
158170

159171
def on_force(icon, item):
160172
global working
173+
global last_state
161174
if working is True:
162175
working = False
163176
disable_sleep()
177+
last_state = "awake"
164178
icon.icon = ICON_FORCE
179+
update_status(icon)
165180
logger.info("KeepAwake force activated")
166181

167182
def on_stop(icon, item):
168183
global working
169184
working = False
170185
icon.icon = ICON_INACTIVE
171-
logger.info("KeepAwake deactivated")
172186
enable_sleep()
187+
update_status(icon)
188+
logger.info("KeepAwake deactivated")
173189

174190
def on_exit(icon, item):
175-
global running
176-
running = False
177191
icon.stop()
192+
stop_event.set() # signal thread to stop immediately
193+
update_status(icon)
178194
logger.info("Exiting KeepAwake")
179195

180196

197+
def restart_icon():
198+
global icon
199+
logger.info("restart tray icon")
200+
if icon:
201+
try:
202+
icon.stop()
203+
except Exception:
204+
pass
205+
run_tray(start_worker=False)
206+
207+
208+
def update_status(icon):
209+
icon.title = f"KeepAwake - {'Running' if working else 'Stopped'}{'' if last_state is None else ' - ' + last_state.capitalize()}"
210+
181211
# --- Tray runner ---
182-
def run_tray():
212+
def run_tray(start_worker=True):
213+
global icon, worker_thread
214+
logger.info("run_tray()")
183215
icon = pystray.Icon(
184216
"keep_awake",
185217
ICON_ACTIVE if working else ICON_INACTIVE,
@@ -191,15 +223,31 @@ def run_tray():
191223
pystray.MenuItem("Exit", on_exit)
192224
)
193225
)
226+
update_status(icon) # set initial status
194227

195-
# Worker mit Icon starten
196-
t = threading.Thread(target=keep_awake, args=(icon,), daemon=True)
197-
t.start()
198-
228+
# Start worker only once
229+
if start_worker and worker_thread is None:
230+
logger.info("starting worker thread")
231+
worker_thread = threading.Thread(target=keep_awake, args=(icon,), daemon=True)
232+
worker_thread.start()
199233
icon.run()
200234

201-
235+
# def explorer_monitor():
236+
# while True:
237+
# # Look for the "Shell_TrayWnd" window (taskbar)
238+
# hwnd = win32gui.FindWindow("Shell_TrayWnd", None)
239+
# if hwnd == 0: # Explorer not running
240+
# time.sleep(2)
241+
# continue
242+
#
243+
# # If icon object exists but tray is gone → restart it
244+
# if icon and not icon.visible:
245+
# logger.info("Explorer restarted → restoring tray icon")
246+
# restart_icon()
247+
#
248+
# time.sleep(5)
202249

203250
if __name__ == "__main__":
204-
# Run tray icon
251+
#logger.info("starting explorer monitor")
205252
run_tray()
253+
#threading.Thread(target=explorer_monitor, daemon=True).start()

0 commit comments

Comments
 (0)