related to memory leak
This commit is contained in:
25 files changed
+610
-68
No files matched your search
@@ -307,6 +307,32 @@ class GlobalMenuDropdowns:
|
||||
active_button = self.dropdown_button_map.get(dropdown_id)
|
||||
manage_button_style_classes(self.all_menu_buttons, active_button)
|
||||
|
||||
def destroy(self):
|
||||
"""Clean up all dropdowns and signal connections"""
|
||||
try:
|
||||
modus_service.disconnect_by_func(self._on_active_app_changed)
|
||||
modus_service.disconnect_by_func(self.changed_dropdown)
|
||||
modus_service.disconnect_by_func(self.hide_dropdowns)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Destroy all dropdown captures
|
||||
dropdown_captures = [
|
||||
getattr(self, "menu_button_dropdown", None),
|
||||
getattr(self, "global_menu_title", None),
|
||||
getattr(self, "global_menu_view", None),
|
||||
getattr(self, "global_menu_window", None),
|
||||
getattr(self, "global_menu_help", None),
|
||||
]
|
||||
for capture in dropdown_captures:
|
||||
try:
|
||||
if capture and hasattr(capture, "destroy"):
|
||||
capture.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
super().destroy()
|
||||
|
||||
|
||||
class GlobalMenu(Box):
|
||||
def __init__(self, parent_window=None, **kwargs):
|
||||
@@ -335,3 +361,12 @@ class GlobalMenu(Box):
|
||||
)
|
||||
mouse_capture = self.dropdown_system.menu_button_dropdown
|
||||
mouse_capture.set_child_window_visible(not mouse_capture.is_visible())
|
||||
|
||||
def destroy(self):
|
||||
"""Clean up the global menu and its dropdowns"""
|
||||
if hasattr(self, "dropdown_system") and self.dropdown_system:
|
||||
try:
|
||||
self.dropdown_system.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
super().destroy()
|
||||
@@ -457,3 +457,102 @@ class BatteryIndicator(Box):
|
||||
|
||||
def hide_controlcenter(self, *args):
|
||||
hide_control_center(self.battery_mousecapture)
|
||||
|
||||
def destroy(self):
|
||||
"""Clean up resources when the indicator is destroyed."""
|
||||
# Disconnect signals
|
||||
try:
|
||||
modus_service.disconnect_by_func(self.on_battery_changed)
|
||||
if hasattr(self, "battery_service") and self.battery_service:
|
||||
self.battery_service.disconnect_by_func(self.on_battery_direct_changed)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Destroy window and widget
|
||||
try:
|
||||
if hasattr(self, "battery_widget") and self.battery_widget:
|
||||
self.battery_widget.destroy()
|
||||
if hasattr(self, "battery_window") and self.battery_window:
|
||||
self.battery_window.destroy()
|
||||
if hasattr(self, "battery_mousecapture") and self.battery_mousecapture:
|
||||
self.battery_mousecapture.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
super().destroy()
|
||||
|
||||
|
||||
# Add destroy methods to other classes in this file as well
|
||||
def add_destroy_to_indicators():
|
||||
# BluetoothIndicator
|
||||
|
||||
def bt_destroy(self):
|
||||
try:
|
||||
modus_service.disconnect_by_func(self.on_bluetooth_changed)
|
||||
if hasattr(self, "bluetooth") and self.bluetooth:
|
||||
self.bluetooth.disconnect_by_func(self.on_bluetooth_direct_changed)
|
||||
self.bluetooth.disconnect_by_func(self.on_device_added)
|
||||
self.bluetooth.disconnect_by_func(self.on_device_removed)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if hasattr(self, "bluetooth_widget") and self.bluetooth_widget:
|
||||
self.bluetooth_widget.destroy()
|
||||
if hasattr(self, "bluetooth_window") and self.bluetooth_window:
|
||||
self.bluetooth_window.destroy()
|
||||
if hasattr(self, "bluetooth_mousecapture") and self.bluetooth_mousecapture:
|
||||
self.bluetooth_mousecapture.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
Box.destroy(self)
|
||||
|
||||
BluetoothIndicator.destroy = bt_destroy
|
||||
|
||||
# NetworkIndicator
|
||||
def net_destroy(self):
|
||||
try:
|
||||
modus_service.disconnect_by_func(self.on_wlan_changed)
|
||||
if hasattr(self, "network_service") and self.network_service:
|
||||
self.network_service.disconnect_by_func(self.on_wifi_device_added)
|
||||
self.network_service.disconnect_by_func(self.on_ethernet_device_added)
|
||||
self.network_service.disconnect_by_func(self.on_network_changed)
|
||||
|
||||
# Also disconnect from the devices themselves if they exist
|
||||
if (
|
||||
hasattr(self.network_service, "wifi_device")
|
||||
and self.network_service.wifi_device
|
||||
):
|
||||
try:
|
||||
self.network_service.wifi_device.disconnect_by_func(
|
||||
self.on_network_direct_changed
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
if (
|
||||
hasattr(self.network_service, "ethernet_device")
|
||||
and self.network_service.ethernet_device
|
||||
):
|
||||
try:
|
||||
self.network_service.ethernet_device.disconnect_by_func(
|
||||
self.on_network_direct_changed
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if hasattr(self, "wifi_widget") and self.wifi_widget:
|
||||
self.wifi_widget.destroy()
|
||||
if hasattr(self, "wifi_window") and self.wifi_window:
|
||||
self.wifi_window.destroy()
|
||||
if hasattr(self, "wifi_mousecapture") and self.wifi_mousecapture:
|
||||
self.wifi_mousecapture.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
Box.destroy(self)
|
||||
|
||||
NetworkIndicator.destroy = net_destroy
|
||||
|
||||
|
||||
# Apply the destroy methods
|
||||
add_destroy_to_indicators()
|
||||
@@ -69,7 +69,9 @@ class WorkspaceIndicator(Box):
|
||||
def update_config(self, new_config: dict):
|
||||
if "hide_special_workspace" in new_config:
|
||||
button_factory = self._get_button_factory()
|
||||
self.remove(self.workspaces)
|
||||
if hasattr(self, "workspaces") and self.workspaces:
|
||||
self.workspaces.destroy()
|
||||
|
||||
self.workspaces = HyprlandWorkspaces(
|
||||
name="workspaces",
|
||||
spacing=4,
|
||||
@@ -77,3 +79,15 @@ class WorkspaceIndicator(Box):
|
||||
)
|
||||
self.add(self.workspaces)
|
||||
self.workspaces.show_all()
|
||||
|
||||
def destroy(self):
|
||||
try:
|
||||
from services.config import _config_handlers
|
||||
|
||||
if self._on_config_changed in _config_handlers:
|
||||
_config_handlers.remove(self._on_config_changed)
|
||||
except Exception:
|
||||
pass
|
||||
if hasattr(self, "workspaces") and self.workspaces:
|
||||
self.workspaces.destroy()
|
||||
Box.destroy(self)
|
||||
@@ -188,6 +188,14 @@ class Panel(Window):
|
||||
self.left_box.children = left_children
|
||||
|
||||
# Indicators (create fresh instances on each rebuild)
|
||||
# First, destroy old indicators to prevent memory leaks
|
||||
for child in list(self.indicators.get_children()):
|
||||
try:
|
||||
child.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
self.indicators.children = []
|
||||
|
||||
indicators_children = []
|
||||
if get_config("battery", True):
|
||||
indicators_children.append(BatteryIndicator())
|
||||
@@ -267,3 +275,36 @@ class Panel(Window):
|
||||
self.chevron_button.get_child().dynamic_file("misc/chevron-left.svg")
|
||||
else:
|
||||
self.chevron_button.get_child().dynamic_file("misc/chevron-right.svg")
|
||||
|
||||
def destroy(self):
|
||||
"""Clean up all signals and components"""
|
||||
try:
|
||||
modus_service.disconnect_by_func(self.on_dnd_changed)
|
||||
notification_service.disconnect_by_func(self.on_notification_count_changed)
|
||||
from services.config import _config_handlers
|
||||
|
||||
if self._on_config_changed in _config_handlers:
|
||||
_config_handlers.remove(self._on_config_changed)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Destroy components
|
||||
for component in [
|
||||
self.globalmenu,
|
||||
self.workspace_indicator,
|
||||
self.recording_indicator,
|
||||
self.indicators,
|
||||
]:
|
||||
try:
|
||||
component.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Destroy MouseCapture windows
|
||||
for mc in [self.control_center, self.notification_center]:
|
||||
try:
|
||||
mc.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
super().destroy()
|
||||
Reference in new issue
Block a user