refactor! : drop subprocess usage and centralize brightness service initialization

This commit is contained in:
sankalp committed 2026-07-08 12:25:02 +05:45
1 parent 06be28535a
commit 5b8d6a62aa
21 files changed
+834 -828

No files matched your search

+3 -5
View File
@@ -1,7 +1,6 @@
import subprocess
from enum import Enum, auto
from fabric.utils import Gdk, GLib, exec_shell_command, logger
from fabric.utils import Gdk, GLib, Gtk, exec_shell_command, logger
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.centerbox import CenterBox
@@ -12,6 +11,7 @@ from fabric.widgets.separator import Separator
from services.bluetooth import BluetoothClient, BluetoothDevice
from shared.widgets.smooth_switch import SmoothSwitch
from shared.window.animated_scrollwindow import AnimatedScrollable
from utils.functions import spawn_detached
from utils.utils import svg_file
@@ -290,8 +290,6 @@ class BluetoothDeviceSlot(Box):
if event.button != 3: # only right-click
return False
from gi.repository import Gtk
menu = Gtk.Menu()
if not self.device.paired:
@@ -567,7 +565,7 @@ class BluetoothConnections(Box):
def open_bluetooth_settings(self, *_):
"""Open Blueman bluetooth manager"""
try:
subprocess.Popen(["blueman-manager"], start_new_session=True)
spawn_detached(["blueman-manager"])
if self.parent and hasattr(self.parent, "hide_controlcenter"):
self.parent.hide_controlcenter()
except FileNotFoundError:
+26 -67
View File
@@ -1,6 +1,4 @@
import subprocess
from fabric.utils import Gdk, GLib, get_relative_path, idle_add, logger
from fabric.utils import Gdk, GLib, idle_add, logger
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.centerbox import CenterBox
@@ -9,6 +7,7 @@ from fabric.widgets.label import Label
from fabric.widgets.overlay import Overlay
from services.brightness import Brightness
from services.modus import is_caffeine_active, toggle_caffeine
from services.network import NetworkClient
from shared.widgets.flat_scale import FlatScale
from shared.window.applet_window import AppletWindow
@@ -24,7 +23,14 @@ from window.controlcenter.per_app_volume import PerAppVolumeControl
from window.controlcenter.player import PlayerBoxStack, get_shared_mpris_manager
from window.controlcenter.wifi import WifiConnections
brightness_service = Brightness()
_brightness_instance: "Brightness | None" = None
def get_brightness_service() -> "Brightness":
global _brightness_instance
if _brightness_instance is None:
_brightness_instance = Brightness()
return _brightness_instance
class ModusControlCenter(AppletWindow):
@@ -48,8 +54,6 @@ class ModusControlCenter(AppletWindow):
# Flight mode and caffeine states
self.flight_mode = False
self.caffeine_mode = False
self._caffeine_process = None
# Loading flags - music and expanded player are no longer lazy loaded
self._per_app_volume_initialized = False
self._signals_connected = False # Track if signals are connected
@@ -111,10 +115,10 @@ class ModusControlCenter(AppletWindow):
h_expand=True,
)
current_brightness = brightness_service.screen_brightness
current_brightness = get_brightness_service().screen_brightness
brightness_percentage = (
int((current_brightness / brightness_service.max_screen) * 100)
if brightness_service.max_screen > 0
int((current_brightness / get_brightness_service().max_screen) * 100)
if get_brightness_service().max_screen > 0
else 50
)
@@ -129,7 +133,7 @@ class ModusControlCenter(AppletWindow):
)
# Only connect brightness controls if brightness service is available
if brightness_service.max_screen > 0:
if get_brightness_service().max_screen > 0:
pass
else:
# Disable brightness scale if no backlight device available
@@ -577,13 +581,15 @@ class ModusControlCenter(AppletWindow):
)
# Connect brightness controls if brightness service is available
if brightness_service.max_screen > 0:
if get_brightness_service().max_screen > 0:
self.brightness_scale.connect("value-changed", self.set_brightness)
self.brightness_scale.connect("scroll-event", self.on_brightness_scroll)
self._signal_connections.append(
(
brightness_service,
brightness_service.connect("screen", self.brightness_changed),
get_brightness_service(),
get_brightness_service().connect(
"screen", self.brightness_changed
),
)
)
@@ -715,23 +721,8 @@ class ModusControlCenter(AppletWindow):
self.per_app_volume_center_box.set_size_request(300, -1)
def _check_initial_states(self):
# Check if caffeine is already running - use faster method
try:
# Use faster check with timeout
result = subprocess.run(
["pgrep", "-f", "modus-inhibit"],
capture_output=True,
text=True,
timeout=0.5, # Add timeout to prevent hanging
)
self.caffeine_mode = bool(result.stdout.strip())
except (subprocess.TimeoutExpired, Exception):
self.caffeine_mode = False
# Flight mode starts as False (normal mode)
self.caffeine_mode = is_caffeine_active()
self.flight_mode = False
# Update initial labels (will be set after widgets are created)
GLib.timeout_add(100, self._update_initial_labels)
def _update_initial_labels(self):
@@ -778,30 +769,13 @@ class ModusControlCenter(AppletWindow):
def toggle_caffeine(self, *_):
try:
if self.caffeine_mode:
inhibit_script = get_relative_path("../../utils/inhibit.py")
subprocess.run(["python3", inhibit_script, "off"], check=False)
self.caffeine_mode = False
if self._caffeine_process:
try:
self._caffeine_process.terminate()
except Exception as e:
logger.error(f"An error occurred: {e}")
self._caffeine_process = None
else:
inhibit_script = get_relative_path("../../utils/inhibit.py")
self._caffeine_process = subprocess.Popen(
["python3", inhibit_script, "on"], start_new_session=True
)
self.caffeine_mode = True
self.caffeine_mode = toggle_caffeine()
self.caffeine_icon.dynamic_file(
"applets/caffeine-on.svg"
if self.caffeine_mode
else "applets/caffeine-off.svg"
)
self.caffeine_status_label.set_label("On" if self.caffeine_mode else "Off")
except Exception as e:
logger.warning(f"Failed to toggle caffeine: {e}")
@@ -816,17 +790,17 @@ class ModusControlCenter(AppletWindow):
if not self._signals_connected:
return
self._updating_brightness = True
brightness_value = int((brightness / 100) * brightness_service.max_screen)
brightness_service.screen_brightness = brightness_value
brightness_value = int((brightness / 100) * get_brightness_service().max_screen)
get_brightness_service().screen_brightness = brightness_value
self._updating_brightness = False
def brightness_changed(self, _, brightness_value):
if not self._signals_connected or self._updating_brightness:
return
if brightness_service.max_screen > 0:
if get_brightness_service().max_screen > 0:
brightness_percentage = int(
(brightness_value / brightness_service.max_screen) * 100
(brightness_value / get_brightness_service().max_screen) * 100
)
GLib.idle_add(
@@ -1214,22 +1188,7 @@ class ModusControlCenter(AppletWindow):
logger.warning(f"Widget cleanup failed: {e}")
def _cleanup_processes(self):
"""Clean up any running processes"""
try:
# Clean up caffeine process
if self._caffeine_process:
try:
self._caffeine_process.terminate()
self._caffeine_process.wait(timeout=1)
except Exception as e:
logger.warning(f"Failed to terminate caffeine process: {e}")
finally:
self._caffeine_process = None
logger.debug("All processes cleaned up successfully")
except Exception as e:
logger.warning(f"Process cleanup failed: {e}")
logger.debug("All processes cleaned up successfully")
def _complete_cleanup(self):
"""Perform complete cleanup of all resources"""
+14 -73
View File
@@ -1,86 +1,30 @@
import subprocess
from fabric.utils import logger
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.label import Label
from services.modus import (
is_night_light_active,
toggle_night_light,
)
from utils.utils import svg_file
class NightLightControl:
"""Control night light using hyprsunset"""
def __init__(self):
self.is_active = False
self._check_initial_state()
def _check_initial_state(self):
"""Check if hyprsunset is currently running"""
try:
result = subprocess.run(
["pgrep", "-f", "hyprsunset"], capture_output=True, text=True
)
self.is_active = bool(result.stdout.strip())
except Exception as e:
logger.warning(f"Failed to check hyprsunset status: {e}")
self.is_active = False
def toggle(self):
"""Toggle night light on/off"""
try:
if self.is_active:
# Turn off night light by killing hyprsunset
subprocess.run(["pkill", "hyprsunset"], check=False)
self.is_active = False
logger.debug("Night light turned off")
else:
# Turn on night light with default temperature (3000K)
subprocess.Popen(["hyprsunset", "-t", "4500"], start_new_session=True)
self.is_active = True
logger.debug("Night light turned on")
return True
except Exception as e:
logger.warning(f"Failed to toggle night light: {e}")
return False
def set_temperature(self, temperature: int):
"""Set night light temperature (1000-6500K)"""
try:
# Kill existing process
subprocess.run(["pkill", "hyprsunset"], check=False)
# Start with new temperature
subprocess.Popen(
["hyprsunset", "-t", str(temperature)], start_new_session=True
)
self.is_active = True
logger.debug(f"Night light temperature set to {temperature}K")
return True
except Exception as e:
logger.warning(f"Failed to set night light temperature: {e}")
return False
def create_night_light_widget(control_center):
"""Create night light widget for control center"""
# Initialize night light control
night_light = NightLightControl()
is_active = is_night_light_active()
# Create icon
night_light_icon = svg_file(
(
"applets/redshift-status-on.svg"
if night_light.is_active
if is_active
else "applets/redshift-status-off.svg"
),
size=42,
)
# Create status label
night_light_status_label = Label(
label="On" if night_light.is_active else "Off",
label="On" if is_active else "Off",
name="nightlight-widget-label",
style_classes="status-label",
max_chars_width=15,
@@ -88,19 +32,16 @@ def create_night_light_widget(control_center):
h_align="start",
)
def toggle_night_light(*_):
"""Toggle night light and update UI"""
if night_light.toggle():
# Update icon
def toggle_ui(*_):
if toggle_night_light():
is_active = is_night_light_active()
night_light_icon.dynamic_file(
"applets/redshift-status-on.svg"
if night_light.is_active
if is_active
else "applets/redshift-status-off.svg"
)
# Update status label
night_light_status_label.set_label("On" if night_light.is_active else "Off")
night_light_status_label.set_label("On" if is_active else "Off")
# Create widget box (similar to bluetooth_widget structure)
night_light_widget = Box(
name="nightlight-widget",
orientation="h",
@@ -109,7 +50,7 @@ def create_night_light_widget(control_center):
Button(
name="nightlight-icon-button",
child=night_light_icon,
on_clicked=toggle_night_light,
on_clicked=toggle_ui,
),
Button(
name="nightlight-info-button",
@@ -130,7 +71,7 @@ def create_night_light_widget(control_center):
night_light_status_label,
],
),
on_clicked=toggle_night_light,
on_clicked=toggle_ui,
),
],
)
+12 -3
View File
@@ -74,6 +74,9 @@ class PerAppVolumeControl(Box):
audio_service.connect("stream-removed", self._on_stream_changed)
)
# Track last known app names to avoid unnecessary rebuilds
self._last_app_names = frozenset()
# Initial population
self._populate_apps()
@@ -84,9 +87,15 @@ class PerAppVolumeControl(Box):
"""Auto-refresh the application list every 2 seconds"""
if self._destroyed:
self._refresh_timer = None
return False # Remove GLib source
self._populate_apps()
return True # Continue the timer
return False
if not audio_service:
return True
apps = audio_service.applications or []
current_names = frozenset(a.name or "" for a in apps)
if current_names != self._last_app_names:
self._last_app_names = current_names
self._populate_apps()
return True
def _on_map(self, *_):
if self._refresh_timer is None:
+7 -5
View File
@@ -1,5 +1,3 @@
import subprocess
from fabric.utils import Gdk, GLib, logger
from fabric.widgets.box import Box
from fabric.widgets.button import Button
@@ -12,7 +10,11 @@ from services.network import NetworkClient
from shared.dialogs.wifi_password_dialog import WiFiPasswordDialog
from shared.widgets.smooth_switch import SmoothSwitch
from shared.window.animated_scrollwindow import AnimatedScrollable
from utils.functions import get_wifi_connecting_icon, get_wifi_icon_for_strength
from utils.functions import (
get_wifi_connecting_icon,
get_wifi_icon_for_strength,
spawn_detached,
)
from utils.utils import svg_file
@@ -107,7 +109,7 @@ class WifiNetworkSlot(Box):
self.dimage.add_style_class("disconnecting")
if self.wifi_service and self.wifi_service._device:
subprocess.Popen(
spawn_detached(
[
"nmcli",
"device",
@@ -472,7 +474,7 @@ class WifiConnections(Box):
def open_network_settings(self, *_):
"""Open NetworkManager connection editor"""
try:
subprocess.Popen(["nm-connection-editor"], start_new_session=True)
spawn_detached(["nm-connection-editor"])
if self.parent and hasattr(self.parent, "hide_controlcenter"):
self.parent.hide_controlcenter()
except FileNotFoundError: