forked from Boria138/PortProtonQt
Compare commits
3 Commits
567203b0b0
...
renovate/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92572bf5a1 | ||
|
438e9737ea
|
|||
|
2d39a4c740
|
@@ -94,7 +94,7 @@ jobs:
|
|||||||
name: Build Arch Package
|
name: Build Arch Package
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container:
|
container:
|
||||||
image: archlinux:base-devel@sha256:06ab929f935145dd65994a89dd06651669ea28d43c812f3e24de990978511821
|
image: archlinux:base-devel@sha256:87a967f07ba6319fc35c8c4e6ce6acdb4343b57aa817398a5d2db57bd8edc731
|
||||||
volumes:
|
volumes:
|
||||||
- /usr:/usr-host
|
- /usr:/usr-host
|
||||||
- /opt:/opt-host
|
- /opt:/opt-host
|
||||||
|
|||||||
@@ -188,4 +188,4 @@ jobs:
|
|||||||
tag_name: v${{ env.VERSION }}
|
tag_name: v${{ env.VERSION }}
|
||||||
prerelease: true
|
prerelease: true
|
||||||
files: release/**/*
|
files: release/**/*
|
||||||
sha256sum: true
|
sha256sum: false
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ jobs:
|
|||||||
needs: changes
|
needs: changes
|
||||||
if: needs.changes.outputs.arch == 'true' || github.event_name == 'workflow_dispatch'
|
if: needs.changes.outputs.arch == 'true' || github.event_name == 'workflow_dispatch'
|
||||||
container:
|
container:
|
||||||
image: archlinux:base-devel@sha256:06ab929f935145dd65994a89dd06651669ea28d43c812f3e24de990978511821
|
image: archlinux:base-devel@sha256:87a967f07ba6319fc35c8c4e6ce6acdb4343b57aa817398a5d2db57bd8edc731
|
||||||
volumes:
|
volumes:
|
||||||
- /usr:/usr-host
|
- /usr:/usr-host
|
||||||
- /opt:/opt-host
|
- /opt:/opt-host
|
||||||
|
|||||||
@@ -3057,54 +3057,72 @@ class MainWindow(QMainWindow):
|
|||||||
Если True — сворачиваем в трей (по умолчанию). Иначе — полностью закрываем.
|
Если True — сворачиваем в трей (по умолчанию). Иначе — полностью закрываем.
|
||||||
"""
|
"""
|
||||||
minimize_to_tray = read_minimize_to_tray()
|
minimize_to_tray = read_minimize_to_tray()
|
||||||
|
|
||||||
|
if minimize_to_tray:
|
||||||
|
# Просто сворачиваем в трей
|
||||||
|
event.ignore()
|
||||||
|
self.hide()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Полное закрытие приложения
|
||||||
|
self.is_exiting = True
|
||||||
|
event.accept()
|
||||||
|
|
||||||
|
# Скрываем и удаляем иконку трея
|
||||||
|
if hasattr(self, "tray_manager") and self.tray_manager.tray_icon:
|
||||||
|
self.tray_manager.tray_icon.hide()
|
||||||
|
self.tray_manager.tray_icon.deleteLater()
|
||||||
|
|
||||||
|
# Сохраняем размеры карточек
|
||||||
save_card_size(self.card_width)
|
save_card_size(self.card_width)
|
||||||
save_auto_card_size(self.auto_card_width)
|
save_auto_card_size(self.auto_card_width)
|
||||||
# Сохраняем настройки окна
|
|
||||||
|
# Сохраняем размеры окна (если не в полноэкранном режиме)
|
||||||
if not read_fullscreen_config():
|
if not read_fullscreen_config():
|
||||||
logger.debug(f"Saving window geometry: {self.width()}x{self.height()}")
|
logger.debug(f"Saving window geometry: {self.width()}x{self.height()}")
|
||||||
save_window_geometry(self.width(), self.height())
|
save_window_geometry(self.width(), self.height())
|
||||||
if hasattr(self, 'is_exiting') and self.is_exiting or not minimize_to_tray:
|
|
||||||
# Принудительное закрытие: завершаем процессы и приложение
|
|
||||||
for proc in self.game_processes:
|
|
||||||
try:
|
|
||||||
parent = psutil.Process(proc.pid)
|
|
||||||
children = parent.children(recursive=True)
|
|
||||||
for child in children:
|
|
||||||
try:
|
|
||||||
logger.debug(f"Terminating child process {child.pid}")
|
|
||||||
child.terminate()
|
|
||||||
except psutil.NoSuchProcess:
|
|
||||||
logger.debug(f"Child process {child.pid} already terminated")
|
|
||||||
psutil.wait_procs(children, timeout=5)
|
|
||||||
for child in children:
|
|
||||||
if child.is_running():
|
|
||||||
logger.debug(f"Killing child process {child.pid}")
|
|
||||||
child.kill()
|
|
||||||
logger.debug(f"Terminating process group {proc.pid}")
|
|
||||||
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
|
||||||
except (psutil.NoSuchProcess, ProcessLookupError) as e:
|
|
||||||
logger.debug(f"Process {proc.pid} already terminated: {e}")
|
|
||||||
|
|
||||||
self.game_processes = [] # Очищаем список процессов
|
# Завершаем все игровые процессы
|
||||||
|
for proc in getattr(self, "game_processes", []):
|
||||||
|
try:
|
||||||
|
parent = psutil.Process(proc.pid)
|
||||||
|
children = parent.children(recursive=True)
|
||||||
|
for child in children:
|
||||||
|
try:
|
||||||
|
logger.debug(f"Terminating child process {child.pid}")
|
||||||
|
child.terminate()
|
||||||
|
except psutil.NoSuchProcess:
|
||||||
|
logger.debug(f"Child process {child.pid} already terminated")
|
||||||
|
|
||||||
# Очищаем таймеры
|
psutil.wait_procs(children, timeout=5)
|
||||||
if hasattr(self, 'games_load_timer') and self.games_load_timer is not None and self.games_load_timer.isActive():
|
for child in children:
|
||||||
self.games_load_timer.stop()
|
if child.is_running():
|
||||||
if hasattr(self, 'settingsDebounceTimer') and self.settingsDebounceTimer is not None and self.settingsDebounceTimer.isActive():
|
logger.debug(f"Killing child process {child.pid}")
|
||||||
self.settingsDebounceTimer.stop()
|
child.kill()
|
||||||
if hasattr(self, 'searchDebounceTimer') and self.searchDebounceTimer is not None and self.searchDebounceTimer.isActive():
|
|
||||||
self.searchDebounceTimer.stop()
|
|
||||||
if hasattr(self, 'checkProcessTimer') and self.checkProcessTimer is not None and self.checkProcessTimer.isActive():
|
|
||||||
self.checkProcessTimer.stop()
|
|
||||||
self.checkProcessTimer.deleteLater()
|
|
||||||
self.checkProcessTimer = None
|
|
||||||
if hasattr(self, 'wine_monitor_timer') and self.wine_monitor_timer is not None:
|
|
||||||
self.wine_monitor_timer.stop()
|
|
||||||
self.wine_monitor_timer.deleteLater()
|
|
||||||
self.wine_monitor_timer = None
|
|
||||||
|
|
||||||
event.accept()
|
logger.debug(f"Terminating process group {proc.pid}")
|
||||||
else:
|
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||||
# Сворачиваем в трей вместо закрытия
|
|
||||||
self.hide()
|
except (psutil.NoSuchProcess, ProcessLookupError) as e:
|
||||||
event.ignore()
|
logger.debug(f"Process {getattr(proc, 'pid', '?')} already terminated: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to terminate process {getattr(proc, 'pid', '?')}: {e}")
|
||||||
|
|
||||||
|
self.game_processes = []
|
||||||
|
|
||||||
|
# Универсальная остановка и удаление таймеров
|
||||||
|
timers = [
|
||||||
|
"games_load_timer",
|
||||||
|
"settingsDebounceTimer",
|
||||||
|
"searchDebounceTimer",
|
||||||
|
"checkProcessTimer",
|
||||||
|
"wine_monitor_timer",
|
||||||
|
]
|
||||||
|
|
||||||
|
for tname in timers:
|
||||||
|
timer = getattr(self, tname, None)
|
||||||
|
if timer and timer.isActive():
|
||||||
|
timer.stop()
|
||||||
|
if timer:
|
||||||
|
timer.deleteLater()
|
||||||
|
setattr(self, tname, None)
|
||||||
|
|||||||
Reference in New Issue
Block a user