feat(src/window): migrate device monitoring to map/unmap events
Ensure monitoring starts only when the widget is shown and stops on hide, preventing timer leaks and unnecessary refreshes
This commit is contained in:
8 files changed
+95
-29
No files matched your search
@@ -357,8 +357,8 @@ class BluetoothConnections(Box):
|
||||
# Initial device update
|
||||
self.update_devices()
|
||||
|
||||
# Start periodic device monitoring for real-time updates
|
||||
self.start_device_monitoring()
|
||||
self.connect("map", lambda *_: self.start_device_monitoring())
|
||||
self.connect("unmap", lambda *_: self.on_hide())
|
||||
|
||||
def toggle_other_devices(self, *_):
|
||||
"""Toggle the visibility of other devices section"""
|
||||
@@ -490,6 +490,10 @@ class BluetoothConnections(Box):
|
||||
finally:
|
||||
self._update_in_progress = False
|
||||
|
||||
def on_hide(self, *_):
|
||||
"""Called when the widget is hidden"""
|
||||
self.stop_device_monitoring()
|
||||
|
||||
def start_device_monitoring(self):
|
||||
"""Start periodic monitoring for device changes"""
|
||||
# Monitor for device changes every 5 seconds (less aggressive)
|
||||
|
||||
@@ -421,13 +421,12 @@ class BluetoothConnections(Box):
|
||||
|
||||
self.connect("destroy", self.on_destroy)
|
||||
self.connect("unmap", self.on_hide)
|
||||
self.connect("map", lambda *_: self.start_device_monitoring())
|
||||
|
||||
self.client.notify("scanning")
|
||||
self.client.notify("enabled")
|
||||
self.update_devices()
|
||||
|
||||
self.start_device_monitoring()
|
||||
|
||||
def handle_user_toggle(self, active: bool):
|
||||
self._switch_lock = True
|
||||
set_bluetooth_enabled_with_fallback(self.client, active)
|
||||
@@ -441,6 +440,7 @@ class BluetoothConnections(Box):
|
||||
|
||||
def on_hide(self, *_):
|
||||
"""Called when the widget is hidden (popup closed)"""
|
||||
self.stop_device_monitoring()
|
||||
if self.other_devices.get_visible():
|
||||
self.other_devices.set_visible(False)
|
||||
self.other_devices_scrolled.snap_to_size(0)
|
||||
|
||||
@@ -77,8 +77,8 @@ class PerAppVolumeControl(Box):
|
||||
# Initial population
|
||||
self._populate_apps()
|
||||
|
||||
# Set up auto-refresh timer for audio streams
|
||||
self._refresh_timer = GLib.timeout_add_seconds(2, self._auto_refresh)
|
||||
self.connect("map", self._on_map)
|
||||
self.connect("unmap", self._on_unmap)
|
||||
|
||||
def _auto_refresh(self):
|
||||
"""Auto-refresh the application list every 2 seconds"""
|
||||
@@ -88,6 +88,15 @@ class PerAppVolumeControl(Box):
|
||||
self._populate_apps()
|
||||
return True # Continue the timer
|
||||
|
||||
def _on_map(self, *_):
|
||||
if self._refresh_timer is None:
|
||||
self._refresh_timer = GLib.timeout_add_seconds(2, self._auto_refresh)
|
||||
|
||||
def _on_unmap(self, *_):
|
||||
if self._refresh_timer is not None:
|
||||
GLib.source_remove(self._refresh_timer)
|
||||
self._refresh_timer = None
|
||||
|
||||
def _go_back(self, *_):
|
||||
"""Return to main control center view"""
|
||||
self.control_center.close_per_app_volume()
|
||||
|
||||
@@ -383,11 +383,11 @@ class WifiConnections(Box):
|
||||
|
||||
self.connect("destroy", self.on_destroy)
|
||||
self.connect("unmap", self.on_hide)
|
||||
|
||||
self.start_network_monitoring()
|
||||
self.connect("map", lambda *_: self.start_network_monitoring())
|
||||
|
||||
def on_hide(self, *_):
|
||||
"""Called when the widget is hidden (popup closed)"""
|
||||
self.stop_network_monitoring()
|
||||
if self.other_networks.get_visible():
|
||||
self.other_networks.set_visible(False)
|
||||
self.other_networks_scrolled.snap_to_size(0)
|
||||
|
||||
+41
-7
@@ -73,16 +73,38 @@ class AppBar(Box):
|
||||
self.setup_app_monitoring()
|
||||
|
||||
def setup_app_monitoring(self):
|
||||
def update_running_apps():
|
||||
try:
|
||||
self.update_dock_apps()
|
||||
except Exception as e:
|
||||
logger.error(f"[AppBar] Error updating apps: {e}")
|
||||
return True
|
||||
self._hyprland_event_handlers = []
|
||||
|
||||
events_to_monitor = [
|
||||
"event::openwindow",
|
||||
"event::closewindow",
|
||||
"event::activewindow",
|
||||
"event::windowtitle",
|
||||
"event::movewindow",
|
||||
"event::workspace",
|
||||
]
|
||||
|
||||
for event in events_to_monitor:
|
||||
handler_id = self._hyprland_connection.connect(
|
||||
event, lambda *_: self.debounced_update_dock_apps()
|
||||
)
|
||||
self._hyprland_event_handlers.append(handler_id)
|
||||
|
||||
self._app_monitor_timer_id = GLib.timeout_add(250, update_running_apps)
|
||||
GLib.idle_add(self.update_dock_apps)
|
||||
|
||||
def debounced_update_dock_apps(self):
|
||||
if hasattr(self, "_dock_update_timer") and self._dock_update_timer:
|
||||
GLib.source_remove(self._dock_update_timer)
|
||||
self._dock_update_timer = GLib.timeout_add(50, self._do_update_dock_apps)
|
||||
|
||||
def _do_update_dock_apps(self):
|
||||
self._dock_update_timer = None
|
||||
try:
|
||||
self.update_dock_apps()
|
||||
except Exception as e:
|
||||
logger.error(f"[AppBar] Error updating apps: {e}")
|
||||
return False
|
||||
|
||||
def update_icon_size(self):
|
||||
"""Update all icons in the dock to the current config size"""
|
||||
desktop_apps = get_desktop_applications(include_hidden=False)
|
||||
@@ -122,6 +144,18 @@ class AppBar(Box):
|
||||
GLib.source_remove(self._app_monitor_timer_id)
|
||||
self._app_monitor_timer_id = None
|
||||
|
||||
if hasattr(self, "_dock_update_timer") and self._dock_update_timer:
|
||||
GLib.source_remove(self._dock_update_timer)
|
||||
self._dock_update_timer = None
|
||||
|
||||
if hasattr(self, "_hyprland_event_handlers"):
|
||||
for handler_id in self._hyprland_event_handlers:
|
||||
try:
|
||||
self._hyprland_connection.disconnect(handler_id)
|
||||
except Exception:
|
||||
pass
|
||||
self._hyprland_event_handlers = []
|
||||
|
||||
# Destroy context menu
|
||||
if self.menu:
|
||||
self.menu.destroy()
|
||||
|
||||
@@ -272,7 +272,17 @@ class Launcher(Window):
|
||||
def close_launcher(self):
|
||||
"""Hide the launcher and clear search."""
|
||||
self.hide()
|
||||
|
||||
# Cancel any pending search timeout to prevent background rendering
|
||||
if hasattr(self, "_search_timeout") and self._search_timeout:
|
||||
GLib.source_remove(self._search_timeout)
|
||||
self._search_timeout = None
|
||||
|
||||
# Temporarily block search handling while clearing the entry
|
||||
self._initializing = True
|
||||
self.search_entry.set_text("")
|
||||
self._initializing = False
|
||||
|
||||
self._clear_results()
|
||||
self.triggered_plugin = None
|
||||
self.active_trigger = ""
|
||||
@@ -435,7 +445,6 @@ class Launcher(Window):
|
||||
for r in all_results
|
||||
)
|
||||
|
||||
# Don't limit results for triggered plugin queries, only for global searches and trigger suggestions
|
||||
if self.triggered_plugin and self.active_trigger:
|
||||
# In trigger mode - show all results from the triggered plugin
|
||||
self.results = all_results
|
||||
@@ -448,8 +457,8 @@ class Launcher(Window):
|
||||
)
|
||||
|
||||
if is_application_search:
|
||||
# Don't limit application search results
|
||||
self.results = all_results
|
||||
# Limit application search results to a reasonable number to prevent lag
|
||||
self.results = all_results[:20]
|
||||
else:
|
||||
# Apply max_results limit for other global searches and trigger suggestions
|
||||
self.results = all_results[: self.max_results]
|
||||
|
||||
@@ -367,7 +367,7 @@ def preload_notification_assets(notification):
|
||||
# Cache notification image if available
|
||||
if hasattr(notification, "image_pixbuf") and notification.image_pixbuf:
|
||||
cache_notification_image(
|
||||
notification.id, notification.image_pixbuf, (35, 35)
|
||||
notification.id, notification.image_pixbuf, (128, 128)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
+20
-10
@@ -85,9 +85,7 @@ class Panel(Window):
|
||||
)
|
||||
setup_cursor_hover(self.control_center_btn, "pointer")
|
||||
|
||||
self.control_center = ModusControlCenter(
|
||||
parent=self, pointing_to=self.control_center_btn
|
||||
)
|
||||
self._control_center_instance = None
|
||||
self.control_center_btn.connect(
|
||||
"clicked",
|
||||
lambda *_: self.control_center.toggle(),
|
||||
@@ -104,9 +102,7 @@ class Panel(Window):
|
||||
)
|
||||
setup_cursor_hover(self.notification_center_btn, "pointer")
|
||||
|
||||
self.notification_center = NotificationCenter(
|
||||
parent=self, pointing_to=self.notification_center_btn
|
||||
)
|
||||
self._notification_center_instance = None
|
||||
|
||||
self.datetime_btn = Button(
|
||||
name="panel-button",
|
||||
@@ -171,10 +167,24 @@ class Panel(Window):
|
||||
def on_notification_count_changed(self, service, *args):
|
||||
self.update_notification_icon()
|
||||
|
||||
def on_notification_icon_clicked(self, *args):
|
||||
count = notification_service.count
|
||||
if count > 0:
|
||||
self.notification_center.toggle()
|
||||
def on_notification_icon_clicked(self, *_):
|
||||
self.notification_center.toggle()
|
||||
|
||||
@property
|
||||
def control_center(self):
|
||||
if self._control_center_instance is None:
|
||||
self._control_center_instance = ModusControlCenter(
|
||||
parent=self, pointing_to=self.control_center_btn
|
||||
)
|
||||
return self._control_center_instance
|
||||
|
||||
@property
|
||||
def notification_center(self):
|
||||
if self._notification_center_instance is None:
|
||||
self._notification_center_instance = NotificationCenter(
|
||||
parent=self, pointing_to=self.notification_center_btn
|
||||
)
|
||||
return self._notification_center_instance
|
||||
|
||||
def update_notification_icon(self):
|
||||
count = notification_service.count
|
||||
|
||||
Reference in new issue
Block a user