Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/vorta/views/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pathlib import Path

from PyQt6 import QtCore, uic
from PyQt6.QtCore import QPoint, Qt
from PyQt6.QtCore import QPoint, Qt, QTimer
from PyQt6.QtCore import pyqtSignal as Signal
from PyQt6.QtGui import QFontMetrics, QKeySequence, QShortcut
from PyQt6.QtWidgets import (
Expand Down Expand Up @@ -380,3 +380,11 @@ def closeEvent(self, event):
elif not SettingsModel.get(key="disable_background_state").value:
self.app.quit()
event.accept()
# Closing only hides the window: Qt keeps the native window and its backing store
# (~28 MB on a Retina display) alive while Vorta sits in the tray. Release them once
# the close has gone through (Qt hides the widget after this handler returns).
QTimer.singleShot(0, self._release_native_window)

def _release_native_window(self):
if not self.isVisible():
self.destroy() # show() creates the native window again
35 changes: 35 additions & 0 deletions tests/unit/test_main_window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest


def test_close_releases_native_window(qapp, qtbot, monkeypatch):
"""
Closing the main window must release its native window (and with it the backing store),
and showing it again must work as before.
"""
main = qapp.main_window
was_visible = main.isVisible()
# Take the tray path in closeEvent(), also where no tray exists (headless CI).
monkeypatch.setattr('vorta.views.main_window.is_system_tray_available', lambda: True)

def shown():
return main.isVisible() and main.windowHandle() is not None

def released():
return not main.isVisible() and main.windowHandle() is None

qapp.open_main_window_action()
qtbot.waitUntil(shown, **pytest._wait_defaults)

main.close()
qtbot.waitUntil(released, **pytest._wait_defaults)

qapp.open_main_window_action()
qtbot.waitUntil(shown, **pytest._wait_defaults)

main.close()
qtbot.waitUntil(released, **pytest._wait_defaults)

# Leave the window as the other tests expect it.
if was_visible:
qapp.open_main_window_action()
qtbot.waitUntil(shown, **pytest._wait_defaults)
Loading