From 02c32a331a1b446c89760ee33a7ff59f0be2d670 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Mon, 8 Sep 2025 07:59:23 +0545 Subject: [PATCH] feat(panel): add Hyprland workspaces indicator with workspace filtering --- main.py | 15 --------- modules/panel/components/workspace.py | 44 ------------------------ modules/panel/main.py | 23 ++++++++----- utils/functions.py | 48 ++++++++------------------- 4 files changed, 29 insertions(+), 101 deletions(-) delete mode 100644 modules/panel/components/workspace.py diff --git a/main.py b/main.py index 1ba20cf..5db1a5f 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,5 @@ -import gi import setproctitle from fabric import Application -from fabric.core import widgets from fabric.utils import get_relative_path, monitor_file from loguru import logger @@ -14,19 +12,6 @@ from modules.panel.main import Panel from modules.switcher import ApplicationSwitcher from modules.widget import Deskwidgets -gi.require_version("Gtk", "3.0") -gi.require_version("Gdk", "3.0") - -# Initialize fontconfig early to prevent warnings -try: - import ctypes - - libfontconfig = ctypes.CDLL("libfontconfig.so.1") - libfontconfig.FcInit() -except: - pass - - # from modules.corners import Corners for log in [ diff --git a/modules/panel/components/workspace.py b/modules/panel/components/workspace.py deleted file mode 100644 index c05dab0..0000000 --- a/modules/panel/components/workspace.py +++ /dev/null @@ -1,44 +0,0 @@ -from fabric.hyprland.widgets import HyprlandWorkspaces, WorkspaceButton -from fabric.widgets.box import Box -import config.data as data -from utils.functions import is_special_workspace_id - -# TODO: Support Multi Monitor - - -class WorkspaceIndicator(Box): - def __init__(self, **kwargs): - super().__init__( - name="workspace-indicator", orientation="h", spacing=4, **kwargs - ) - - # Create workspace widget with custom button factory if filtering is enabled - if data.HIDE_SPECIAL_WORKSPACE: - self.workspaces = HyprlandWorkspaces( - name="workspaces", - spacing=4, - buttons_factory=self._create_filtered_button, - ) - else: - self.workspaces = HyprlandWorkspaces( - name="workspaces", - spacing=4, - buttons_factory=lambda ws_id: WorkspaceButton( - id=ws_id, label=str(ws_id) - ), - ) - - self.add(self.workspaces) - self.show_all() - - def _is_special_workspace_id(self, ws_id): - return is_special_workspace_id(ws_id) - - def _create_filtered_button(self, ws_id): - if data.HIDE_SPECIAL_WORKSPACE and self._is_special_workspace_id(ws_id): - # Return None or an empty widget to hide special workspaces - return None - - return WorkspaceButton(id=ws_id, label=str(ws_id)) - - diff --git a/modules/panel/main.py b/modules/panel/main.py index 5228e7c..9008264 100644 --- a/modules/panel/main.py +++ b/modules/panel/main.py @@ -1,3 +1,4 @@ +from fabric.hyprland.widgets import HyprlandWorkspaces, WorkspaceButton from fabric.system_tray.widgets import SystemTray from fabric.utils import get_relative_path from fabric.widgets.box import Box @@ -6,6 +7,8 @@ from fabric.widgets.centerbox import CenterBox from fabric.widgets.datetime import DateTime from fabric.widgets.revealer import Revealer from fabric.widgets.svg import Svg + +import config.data as data from modules.controlcenter.main import ModusControlCenter from modules.notification.notification_center import NotificationCenter from modules.panel.components.enhanced_system_tray import apply_enhanced_system_tray @@ -16,12 +19,12 @@ from modules.panel.components.indicators import ( ) from modules.panel.components.menubar import MenuBar from modules.panel.components.recording_indicator import RecordingIndicator -from modules.panel.components.workspace import WorkspaceIndicator from modules.todo.todo_widget import TodoListCapture +from services.modus import notification_service +from utils.functions import is_special_workspace_id from utils.roam import modus_service from widgets.mousecapture import MouseCapture from widgets.wayland import WaylandWindow as Window -from services.modus import notification_service # Apply enhanced system tray icon handling apply_enhanced_system_tray() @@ -41,6 +44,16 @@ class Panel(Window): self.launcher = kwargs.get("launcher", None) self.menubar = MenuBar(parent_window=self) + self.workspace_indicator = HyprlandWorkspaces( + name="workspaces", + spacing=4, + buttons_factory=lambda ws_id: ( + None + if data.HIDE_SPECIAL_WORKSPACE and is_special_workspace_id(ws_id) + else WorkspaceButton(id=ws_id, label=str(ws_id)) + ), + ) + self.imac = Button( name="panel-button", child=Svg( @@ -50,10 +63,7 @@ class Panel(Window): on_clicked=lambda *_: self.menubar.show_system_dropdown(self.imac), ) - # DND indicator - REMOVED - self.tray = SystemTray(name="system-tray", spacing=4, icon_size=20) - self.tray_revealer = Revealer( name="tray-revealer", child=self.tray, @@ -140,9 +150,6 @@ class Panel(Window): self.recording_indicator = RecordingIndicator() - # Workspace indicator - self.workspace_indicator = WorkspaceIndicator() - self.children = CenterBox( name="panel", start_children=Box( diff --git a/utils/functions.py b/utils/functions.py index edbf259..7226ca9 100644 --- a/utils/functions.py +++ b/utils/functions.py @@ -66,7 +66,7 @@ def get_wifi_icon_for_strength(strength: int) -> str: current_dir = os.path.dirname(os.path.abspath(__file__)) # Get the project root (parent of utils directory) project_root = os.path.dirname(current_dir) - + if strength >= 80: icon_name = "network-wireless-100.svg" elif strength >= 60: @@ -94,20 +94,14 @@ def get_wifi_connecting_icon() -> str: current_dir = os.path.dirname(os.path.abspath(__file__)) # Get the project root (parent of utils directory) project_root = os.path.dirname(current_dir) - - return os.path.join(project_root, "config", "assets", "icons", "wifi", "wifi-connecting.svg") + + return os.path.join( + project_root, "config", "assets", "icons", "wifi", "wifi-connecting.svg" + ) +# Function to check if a workspace ID is special def is_special_workspace_id(ws_id) -> bool: - """ - Check if a workspace ID represents a special workspace. - - Args: - ws_id: Workspace ID (can be int, string, or other types) - - Returns: - True if the workspace is special, False otherwise - """ try: # Convert to int if it's a string workspace_id = int(ws_id) @@ -120,33 +114,23 @@ def is_special_workspace_id(ws_id) -> bool: return False +# Function to check if a client is on a special workspace def is_special_workspace(client: dict) -> bool: - """ - Check if a client is in a special workspace. - - Args: - client: Client data dictionary from Hyprland - - Returns: - True if the client is in a special workspace, False otherwise - """ if "workspace" not in client: return False workspace = client["workspace"] - + # Check workspace name first if "name" in workspace: - workspace_name = str(workspace["name"]) - # Special workspaces typically start with "special:" or have negative IDs - if workspace_name.startswith("special:"): + workspace_name = workspace["name"] + if is_special_workspace_id(workspace_name): return True # Check workspace ID if "id" in workspace: workspace_id = workspace["id"] - # Special workspaces have negative IDs - if workspace_id < 0: + if is_special_workspace_id(workspace_id): return True return False @@ -155,20 +139,16 @@ def is_special_workspace(client: dict) -> bool: def escape_markup_text(text: str) -> str: """ Escape special characters in text to make it safe for Pango markup. - + Args: text: Raw text that may contain special characters - + Returns: Escaped text safe for use in Pango markup """ if not text or not isinstance(text, str): return "" - + # Use html.escape to escape XML/HTML special characters # This handles &, <, >, and quotes return html.escape(text) - - - -