feat(panel): add Hyprland workspaces indicator with workspace filtering
This commit is contained in:
4 files changed
+29
-101
No files matched your search
@@ -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 [
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
+15
-8
@@ -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(
|
||||
|
||||
+14
-34
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user