import os # App-capture typelib path (built via meson in src/window/switcher/app-capture/builddir) # Must be set before gi is imported so the typelib search path includes it. _app_capture_builddir = os.path.join( os.path.dirname(__file__), "window", "switcher", "app-capture", "builddir" ) if os.path.isdir(_app_capture_builddir): _cur = os.environ.get("GI_TYPELIB_PATH", "") if _app_capture_builddir not in _cur.split(os.pathsep): os.environ["GI_TYPELIB_PATH"] = _app_capture_builddir + ( os.pathsep + _cur if _cur else "" ) from fabric import Application from fabric.utils import get_relative_path, logger, monitor_file from services.config import config from services.desktop_widget import DesktopWidgetService from services.keyboard_layout import KeyboardLayout from services.sysauth import SysauthService from shared.data import APP_NAME, load_config from utils.functions import set_process_name from utils.gtk_utils import generate_colors_from_wallpaper from window.dock import Dock from window.lock import LockScreenWrapper from window.notification.notification import ModusNoti from window.osd.main import OSDWindow from window.panel.main import Panel from window.screencapture import ScreenCaptureWindow from window.settings.main import get_settings_window from window.spotlight.main import SpotlightWindow from window.switcher import ApplicationSwitcher def setup_logger(): for log in [ "fabric", "services", "window", "utils", "window.globalmenu", "LIBDBUSMENU-GLIB", "libdbusmenu-glib", ]: logger.disable(log) _debug = config().get("debug", False) if not _debug: logger.disable("modus_plugin_builtin_emoji") else: logger.enable("fabric") logger.enable("services") logger.enable("window") logger.enable("utils") logger.enable("window.globalmenu") def setup_css(app): # Generate colors.css if it doesn't exist colors_css_path = get_relative_path("styles/colors.css") if not os.path.exists(colors_css_path): default_wallpaper = get_relative_path("assets/wallpaper_example/example-1.png") if os.path.exists(default_wallpaper): generate_colors_from_wallpaper(default_wallpaper) def set_css(): app.set_stylesheet_from_file(get_relative_path("styles/main.css")) app.set_css = set_css app.set_css() css_monitors = [] for root, dirs, files in os.walk(get_relative_path("styles/")): monitor = monitor_file(root) monitor.connect("changed", lambda *_: set_css()) css_monitors.append(monitor) def cleanup_css_monitors(*args): for m in css_monitors: try: m.cancel() except Exception as e: logger.warning(f"[main] m.cancel() failed: {e}") app.connect("shutdown", cleanup_css_monitors) def main(): set_process_name(APP_NAME) load_config() setup_logger() # Initialize the Application first so it can manage styles globally app = Application(f"{APP_NAME}") # Set up styling before creating windows to prevent unstyled flashes setup_css(app) # Initialize Polkit authentication agent sysauth = SysauthService() sysauth.start() switcher = ApplicationSwitcher() panel = Panel() modusnoti = ModusNoti() spotlight = SpotlightWindow() panel.set_spotlight_toggle(spotlight.toggle) dock = Dock() osd = OSDWindow() screencapture = ScreenCaptureWindow() settings = get_settings_window() # Register windows with the application for w in [ panel, modusnoti, osd, switcher, dock, screencapture, spotlight, ]: app.add_window(w) # Inject into the executing module's namespace (__main__) # This allows fabric-cli exec to execute commands flawlessly. import __main__ __main__.app = app __main__.switcher = switcher __main__.panel = panel __main__.modusnoti = modusnoti __main__.spotlight = spotlight __main__.dock = dock __main__.osd = osd __main__.osd_show_audio = osd.osd_show_audio __main__.osd_show_brightness = osd.osd_show_brightness __main__.screencapture = screencapture __main__.lock_screen = LockScreenWrapper() __main__.switch_keyboard_layout = KeyboardLayout.switch_keyboard_layout __main__.settings = settings __main__.desktop_widgets = DesktopWidgetService.get_instance() app.run() if __name__ == "__main__": main()