initial commit
This commit is contained in:
137 files changed
+23845
-9
No files matched your search
@@ -0,0 +1,10 @@
|
||||
from .battery import *
|
||||
from .bluetooth import *
|
||||
from .idle import *
|
||||
from .stats import *
|
||||
from .microphone import *
|
||||
from .network import *
|
||||
from .powerprofile import *
|
||||
from .taskbar import *
|
||||
from .volume import *
|
||||
from .workspace import *
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,68 @@
|
||||
import psutil
|
||||
from fabric import Fabricator
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.overlay import Overlay
|
||||
from fabric.widgets.circularprogressbar import CircularProgressBar
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class BatteryLabel(Box):
|
||||
ICONS_CHARGING = [
|
||||
"battery_charging_20",
|
||||
"battery_charging_20",
|
||||
"battery_charging_20",
|
||||
"battery_charging_30",
|
||||
"battery_charging_30",
|
||||
"battery_charging_50",
|
||||
"battery_charging_60",
|
||||
"battery_charging_80",
|
||||
"battery_charging_80",
|
||||
"battery_charging_90",
|
||||
"battery_charging_full",
|
||||
]
|
||||
ICONS_NOT_CHARGING = [
|
||||
"battery_alert",
|
||||
"battery_1_bar",
|
||||
"battery_1_bar",
|
||||
"battery_2_bar",
|
||||
"battery_2_bar",
|
||||
"battery_3_bar",
|
||||
"battery_4_bar",
|
||||
"battery_4_bar",
|
||||
"battery_5_bar",
|
||||
"battery_6_bar",
|
||||
"battery_full",
|
||||
]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Fabricator(interval=1000, poll_from=self.update_battery_status)
|
||||
|
||||
def update_battery_status(self, *_):
|
||||
battery = psutil.sensors_battery()
|
||||
if battery is None:
|
||||
self.hide()
|
||||
return
|
||||
is_charging = battery.power_plugged if battery else False
|
||||
icons = self.ICONS_CHARGING if is_charging else self.ICONS_NOT_CHARGING
|
||||
battery_percent = round(battery.percent)
|
||||
index = min(max(battery_percent // 10, 0), 10)
|
||||
battery_icon = MaterialIcon(icons[index], size=16)
|
||||
|
||||
self.progress_bar = CircularProgressBar(
|
||||
name="progress", line_style="round", line_width=1, size=24
|
||||
)
|
||||
|
||||
self.battery_overlay = Overlay(child=self.progress_bar, overlays=battery_icon)
|
||||
|
||||
self.children = self.battery_overlay
|
||||
|
||||
battery_percent = round(battery.percent)
|
||||
self.progress_bar.value = battery_percent / 100
|
||||
# self.show() if battery_percent < 100 else self.hide()
|
||||
|
||||
self.set_tooltip_text(
|
||||
f"Battery: {battery_percent}%\nStatus: {'Charging' if is_charging else 'Discharging'}"
|
||||
)
|
||||
|
||||
return True
|
||||
@@ -0,0 +1,34 @@
|
||||
from fabric.bluetooth import BluetoothClient
|
||||
from fabric.widgets.box import Box
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class BluetoothIndicator(Box):
|
||||
ICON_ENABLED = "bluetooth"
|
||||
ICON_DISABLED = "bluetooth_disabled"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.bluetooth_client = BluetoothClient()
|
||||
|
||||
self.bluetooth_icon = None
|
||||
|
||||
self.bluetooth_client.connect("changed", self.update_bluetooth_status)
|
||||
|
||||
self.update_bluetooth_status()
|
||||
|
||||
def update_bluetooth_status(self, *_):
|
||||
icon_label = (
|
||||
self.ICON_ENABLED if self.bluetooth_client.enabled else self.ICON_DISABLED
|
||||
)
|
||||
|
||||
new_icon = MaterialIcon(icon_label, size=16)
|
||||
|
||||
if self.bluetooth_icon:
|
||||
self.remove(self.bluetooth_icon)
|
||||
|
||||
self.bluetooth_icon = new_icon
|
||||
self.add(self.bluetooth_icon)
|
||||
|
||||
def on_destroy(self):
|
||||
self.bluetooth_client.disconnect("changed", self.update_bluetooth_status)
|
||||
@@ -0,0 +1,27 @@
|
||||
from fabric import Fabricator
|
||||
from fabric.utils import exec_shell_command
|
||||
from fabric.widgets.box import Box
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class IdleIndicator(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.idle_icon = self.create_idle_icon()
|
||||
self.fabricator = Fabricator(interval=1000, poll_from=self.check_idle_status)
|
||||
|
||||
self.children = [self.idle_icon]
|
||||
|
||||
def create_idle_icon(self):
|
||||
return MaterialIcon("coffee", 16)
|
||||
|
||||
def check_idle_status(self, *_):
|
||||
output = exec_shell_command("pidof wayland-idle-inhibitor.py")
|
||||
is_idle = bool(str(output).strip())
|
||||
self.update_idle_status(is_idle)
|
||||
|
||||
def update_idle_status(self, is_idle):
|
||||
if is_idle:
|
||||
self.idle_icon.set_visible(True)
|
||||
else:
|
||||
self.idle_icon.set_visible(False)
|
||||
@@ -0,0 +1,33 @@
|
||||
from fabric.audio.service import Audio
|
||||
from fabric.widgets.box import Box
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class MicrophoneIndicator(Box):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.audio_service = Audio()
|
||||
self.microphone_icon = self.create_microphone_icon()
|
||||
|
||||
self.audio_service.connect("microphone_changed", self.update_microphone_status)
|
||||
self.update_microphone_status()
|
||||
|
||||
self.children = (self.microphone_icon,)
|
||||
|
||||
def create_microphone_icon(self):
|
||||
return MaterialIcon("mic_off", size=16)
|
||||
|
||||
def update_microphone_status(self, *args):
|
||||
current_microphone = self.audio_service.microphone
|
||||
|
||||
if current_microphone:
|
||||
is_muted = current_microphone.muted
|
||||
icon_name = "mic_off" if is_muted else "mic"
|
||||
|
||||
self.microphone_icon.set_label(icon_name)
|
||||
self.microphone_icon.set_visible(is_muted)
|
||||
else:
|
||||
self.microphone_icon.set_visible(False)
|
||||
|
||||
return True
|
||||
@@ -0,0 +1,84 @@
|
||||
import subprocess
|
||||
|
||||
import psutil
|
||||
from fabric import Fabricator
|
||||
from fabric.widgets.box import Box
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class NetworkIndicator(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.update_interval = 5000 # Increased interval to 5 seconds
|
||||
self.last_status = None
|
||||
self.wifi_strength_cache = None
|
||||
self.fabricator = Fabricator(
|
||||
interval=self.update_interval,
|
||||
poll_from=self.update_network_status,
|
||||
)
|
||||
|
||||
def update_network_status(self, *_):
|
||||
current_status = self.get_network_status()
|
||||
if current_status != self.last_status:
|
||||
self.update_icon(current_status)
|
||||
self.last_status = current_status
|
||||
return True
|
||||
|
||||
def update_icon(self, current_status):
|
||||
self.icon_label = MaterialIcon(current_status, size=16)
|
||||
self.children = (self.icon_label,)
|
||||
|
||||
def get_network_status(self):
|
||||
if self.is_ethernet_connected():
|
||||
return "lan"
|
||||
if self.is_wifi_connected():
|
||||
return self.get_wifi_strength_icon()
|
||||
return "signal_wifi_off"
|
||||
|
||||
def get_wifi_strength_icon(self):
|
||||
wifi_strength = self.check_wifi_strength()
|
||||
if wifi_strength is not None:
|
||||
self.wifi_strength_cache = wifi_strength # Cache the result
|
||||
else:
|
||||
wifi_strength = self.wifi_strength_cache # Use cached value if available
|
||||
|
||||
return self.wifi_signal_icon(wifi_strength)
|
||||
|
||||
def wifi_signal_icon(self, strength):
|
||||
if strength is None or strength <= -100:
|
||||
return "signal_wifi_0_bar"
|
||||
if strength > -50:
|
||||
return "signal_wifi_4_bar"
|
||||
if strength > -60:
|
||||
return "network_wifi_3_bar"
|
||||
if strength > -70:
|
||||
return "network_wifi_2_bar"
|
||||
return "network_wifi_1_bar"
|
||||
|
||||
def check_wifi_strength(self):
|
||||
try:
|
||||
result = subprocess.run(["iwconfig"], capture_output=True, text=True)
|
||||
for line in result.stdout.splitlines():
|
||||
if "Signal level" in line:
|
||||
signal_level = line.split("Signal level=")[1].split(" ")[0]
|
||||
return int(signal_level.strip().replace("dBm", ""))
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def is_wifi_connected(self):
|
||||
return any(
|
||||
self._is_interface_up(interface, ["wlan", "wifi"])
|
||||
for interface in psutil.net_if_addrs()
|
||||
)
|
||||
|
||||
def is_ethernet_connected(self):
|
||||
return any(
|
||||
self._is_interface_up(interface, ["enp", "eth"])
|
||||
for interface in psutil.net_if_addrs()
|
||||
)
|
||||
|
||||
def _is_interface_up(self, interface, keywords):
|
||||
if any(substring in interface.lower() for substring in keywords):
|
||||
return psutil.net_if_stats().get(interface, {}).isup
|
||||
return False
|
||||
@@ -0,0 +1,44 @@
|
||||
from fabric import Fabricator
|
||||
from fabric.utils import exec_shell_command
|
||||
from fabric.widgets.box import Box
|
||||
from snippets import MaterialIcon
|
||||
|
||||
PROFILE_ICONS = {
|
||||
"power-saver": "data_saver_on",
|
||||
"balanced": None,
|
||||
"performance": "mode_heat",
|
||||
}
|
||||
|
||||
|
||||
class PowerProfileIndicator(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.profile_icon = None
|
||||
|
||||
self.fabricator = Fabricator(interval=1000, poll_from=self.update_power_profile)
|
||||
|
||||
def update_power_profile(self, *_):
|
||||
profile = self.get_power_profile()
|
||||
self.update_icon(profile)
|
||||
return True
|
||||
|
||||
def get_power_profile(self):
|
||||
result = exec_shell_command("powerprofilesctl get")
|
||||
return result.strip() or "power-saver"
|
||||
|
||||
def update_icon(self, profile):
|
||||
icon_name = PROFILE_ICONS.get(profile)
|
||||
|
||||
new_icon = MaterialIcon(icon_name, 16) if icon_name else None
|
||||
|
||||
if self.profile_icon:
|
||||
self.remove(self.profile_icon)
|
||||
|
||||
if new_icon:
|
||||
self.profile_icon = new_icon
|
||||
self.add(self.profile_icon)
|
||||
else:
|
||||
if self.profile_icon:
|
||||
self.profile_icon.hide()
|
||||
self.profile_icon = None
|
||||
@@ -0,0 +1,94 @@
|
||||
from time import sleep
|
||||
import psutil
|
||||
from fabric import Fabricator
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.circularprogressbar import CircularProgressBar
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.overlay import Overlay
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class SystemInfo(Button):
|
||||
ICONS = [
|
||||
("CPU", "settings_motion_mode"),
|
||||
("Swap", "swap_horiz"),
|
||||
("RAM", "memory_alt"),
|
||||
("Temp", "thermometer"),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(child=self._initialize_content())
|
||||
|
||||
Fabricator(
|
||||
poll_from=self._refresh_system_info,
|
||||
stream=True,
|
||||
on_changed=lambda fab, data: self._update_ui(data),
|
||||
)
|
||||
|
||||
def _initialize_content(self):
|
||||
self.box = Box(orientation="h", name="tray")
|
||||
self.progress_bars = {}
|
||||
self.labels = {}
|
||||
self.icons = {}
|
||||
|
||||
for system, icon_name in self.ICONS:
|
||||
self._create_system_item(system, icon_name)
|
||||
|
||||
return self.box
|
||||
|
||||
def _create_system_item(self, system, icon_name):
|
||||
self.progress_bars[system] = self._create_progress_bar()
|
||||
self.labels[system] = self._create_label()
|
||||
self.icons[system] = self._create_icon(icon_name)
|
||||
|
||||
overlay = Overlay(
|
||||
child=self.progress_bars[system], overlays=[self.icons[system]]
|
||||
)
|
||||
self.box.pack_start(overlay, False, False, 0)
|
||||
self.box.pack_start(self.labels[system], False, False, 0)
|
||||
|
||||
def _create_progress_bar(self):
|
||||
return CircularProgressBar(
|
||||
name="progress", line_style="round", line_width=1, size=24
|
||||
)
|
||||
|
||||
def _create_label(self):
|
||||
return Label(style="font-size:14px; margin: 4px;")
|
||||
|
||||
def _create_icon(self, icon_name):
|
||||
return MaterialIcon(icon_name, size=16)
|
||||
|
||||
def _refresh_system_info(self, fab: Fabricator):
|
||||
while True:
|
||||
yield {
|
||||
"CPU": round(psutil.cpu_percent()),
|
||||
"RAM": round(psutil.virtual_memory().percent),
|
||||
"Swap": round(psutil.swap_memory().percent),
|
||||
"Temp": self._get_device_temperature(),
|
||||
}
|
||||
sleep(1)
|
||||
|
||||
@staticmethod
|
||||
def _get_device_temperature():
|
||||
try:
|
||||
temps = psutil.sensors_temperatures()
|
||||
if "coretemp" in temps:
|
||||
return round(temps["coretemp"][0].current, 1)
|
||||
elif "cpu_thermal" in temps:
|
||||
return round(temps["cpu_thermal"][0].current, 1)
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _update_ui(self, usages):
|
||||
for system, usage in usages.items():
|
||||
if usage is None:
|
||||
usage = 0
|
||||
self.labels[system].set_label("N/A")
|
||||
else:
|
||||
usage = int(usage)
|
||||
|
||||
self.progress_bars[system].value = usage / 100
|
||||
self.labels[system].set_label(f"{usage}")
|
||||
self.progress_bars[system].set_tooltip_text(f"{system} Usage: {usage}%")
|
||||
@@ -0,0 +1,154 @@
|
||||
import json
|
||||
import os
|
||||
from typing import TypedDict
|
||||
|
||||
from fabric.hyprland.widgets import get_hyprland_connection
|
||||
from fabric.utils import exec_shell_command_async
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.image import Image
|
||||
from gi.repository import GdkPixbuf, GLib, Gtk
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class PagerClient(TypedDict):
|
||||
title: str
|
||||
initialClass: str
|
||||
mapped: bool
|
||||
hidden: bool
|
||||
address: str
|
||||
|
||||
|
||||
class TaskBar(Box):
|
||||
def __init__(self, icon_size: int = 20, **kwargs):
|
||||
super().__init__(
|
||||
orientation="h",
|
||||
spacing=7,
|
||||
name="taskbar",
|
||||
**kwargs,
|
||||
)
|
||||
self.connection = get_hyprland_connection()
|
||||
self.icon_size = icon_size
|
||||
self.icon_theme = Gtk.IconTheme.get_default()
|
||||
|
||||
self.set_visible(False)
|
||||
|
||||
if self.connection.ready:
|
||||
self.render_with_delay()
|
||||
else:
|
||||
self.connection.connect("event::ready", lambda *_: self.render_with_delay())
|
||||
|
||||
for event in (
|
||||
"activewindow",
|
||||
"openwindow",
|
||||
"closewindow",
|
||||
"changefloatingmode",
|
||||
):
|
||||
self.connection.connect("event::" + event, lambda *_: self.render(None))
|
||||
|
||||
def render_with_delay(self, *_):
|
||||
GLib.timeout_add(101, self.render)
|
||||
|
||||
def render(self, *_):
|
||||
self.children = []
|
||||
|
||||
clients = self.fetch_clients()
|
||||
active_window_address = self.get_active_window_address()
|
||||
|
||||
visible_clients = [
|
||||
client for client in clients if client["mapped"] and not client["hidden"]
|
||||
]
|
||||
|
||||
if visible_clients:
|
||||
for client in visible_clients:
|
||||
window_class = client["initialClass"].lower()
|
||||
icon = self.bake_window_icon(window_class)
|
||||
|
||||
button = Button(image=icon, tooltip_text=client["title"])
|
||||
if client["address"] == active_window_address:
|
||||
button.add_style_class("activated")
|
||||
button.connect(
|
||||
"button-press-event",
|
||||
self.on_icon_click,
|
||||
client["address"],
|
||||
)
|
||||
|
||||
self.add(button)
|
||||
self.set_visible(True)
|
||||
self.show_all()
|
||||
else:
|
||||
self.set_visible(False)
|
||||
|
||||
self.set_visible(len(self.children) > 0)
|
||||
if self.children:
|
||||
self.show_all()
|
||||
|
||||
def get_active_window_address(self) -> str:
|
||||
active_window_info = json.loads(
|
||||
self.connection.send_command("j/activewindow").reply.decode()
|
||||
)
|
||||
return active_window_info.get("address", "")
|
||||
|
||||
def on_icon_click(self, widget, event, address):
|
||||
exec_shell_command_async(
|
||||
f"hyprctl dispatch focuswindow address:{address}", lambda *_: None
|
||||
)
|
||||
|
||||
def fetch_clients(self) -> list[PagerClient]:
|
||||
return json.loads(self.connection.send_command("j/clients").reply.decode())
|
||||
|
||||
def bake_window_icon(
|
||||
self,
|
||||
window_class: str,
|
||||
fallback_icon: str = "image-missing",
|
||||
) -> Image:
|
||||
icon_name = self.get_icon_from_desktop_entry(window_class)
|
||||
|
||||
if icon_name:
|
||||
pixbuf = self.load_icon(icon_name)
|
||||
else:
|
||||
pixbuf = self.load_icon(window_class, fallback_icon)
|
||||
|
||||
return Image(pixbuf=pixbuf, size=self.icon_size)
|
||||
|
||||
def get_icon_from_desktop_entry(self, window_class: str) -> str:
|
||||
for data_dir in GLib.get_system_data_dirs():
|
||||
applications_dir = os.path.join(data_dir, "applications")
|
||||
|
||||
if os.path.isdir(applications_dir):
|
||||
for desktop_file in os.listdir(applications_dir):
|
||||
if desktop_file.endswith(".desktop"):
|
||||
file_path = os.path.join(applications_dir, desktop_file)
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
app_name = None
|
||||
icon_name = None
|
||||
for line in f:
|
||||
if line.startswith("Name="):
|
||||
app_name = line.split("=", 2)[1].strip().lower()
|
||||
elif line.startswith("Icon=") and app_name:
|
||||
icon_name = line.split("=", 2)[1].strip()
|
||||
if window_class in app_name:
|
||||
return icon_name
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading {file_path}: {e}")
|
||||
return None
|
||||
|
||||
def load_icon(
|
||||
self,
|
||||
icon_name: str,
|
||||
fallback_icon: str = "image-missing",
|
||||
) -> GdkPixbuf.Pixbuf:
|
||||
try:
|
||||
pixbuf = self.icon_theme.load_icon(
|
||||
icon_name,
|
||||
self.icon_size,
|
||||
Gtk.IconLookupFlags.FORCE_SIZE,
|
||||
)
|
||||
except Exception:
|
||||
pixbuf = self.icon_theme.load_icon(
|
||||
fallback_icon,
|
||||
self.icon_size,
|
||||
Gtk.IconLookupFlags.FORCE_SIZE,
|
||||
)
|
||||
return pixbuf
|
||||
@@ -0,0 +1,81 @@
|
||||
from fabric import Fabricator
|
||||
from fabric.utils import exec_shell_command
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from snippets import MaterialIcon
|
||||
from services import audio
|
||||
|
||||
VOLUME_ICONS = {
|
||||
"muted": "volume_off",
|
||||
"low": "volume_mute",
|
||||
"medium-low": "volume_down",
|
||||
"medium-high": "volume_up",
|
||||
"high": "volume_up",
|
||||
}
|
||||
|
||||
|
||||
class VolumeIndicator(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.audio_service = audio
|
||||
self.volume_icon_button = self.create_volume_icon()
|
||||
|
||||
self.volume_icon_button.connect("button-press-event", self.on_button_press)
|
||||
self.audio_service.connect("changed", self.update_volume_status)
|
||||
|
||||
Fabricator(interval=1000, poll_from=self.update_volume_status)
|
||||
self.children = (self.volume_icon_button,)
|
||||
|
||||
def create_volume_icon(self):
|
||||
icon = MaterialIcon(VOLUME_ICONS["muted"], size=16)
|
||||
button = Button(child=icon)
|
||||
button.icon_widget = icon
|
||||
return button
|
||||
|
||||
def on_button_press(self, widget, event):
|
||||
if event.button == 1:
|
||||
self.toggle_mute()
|
||||
elif event.button == 3:
|
||||
self.open_audio_settings()
|
||||
|
||||
def toggle_mute(self):
|
||||
current_stream = self.audio_service.speaker
|
||||
if current_stream:
|
||||
current_stream.muted = not current_stream.muted
|
||||
# self.update_volume_status()
|
||||
|
||||
def open_audio_settings(self):
|
||||
exec_shell_command("pavucontrol")
|
||||
|
||||
def update_volume_status(self, *_):
|
||||
current_stream = self.audio_service.speaker
|
||||
if current_stream:
|
||||
self.update_icon(current_stream)
|
||||
|
||||
return True
|
||||
|
||||
def update_icon(self, stream):
|
||||
if stream.muted:
|
||||
icon_name = VOLUME_ICONS["muted"]
|
||||
volume_percentage = 0
|
||||
tooltip_text = "Volume Muted"
|
||||
else:
|
||||
volume_level = stream.volume
|
||||
icon_name = self.get_volume_icon(volume_level)
|
||||
volume_percentage = int(volume_level)
|
||||
tooltip_text = f"Volume: {volume_percentage}%"
|
||||
|
||||
self.volume_icon_button.icon_widget.set_label(icon_name)
|
||||
|
||||
self.volume_icon_button.set_tooltip_text(tooltip_text)
|
||||
|
||||
def get_volume_icon(self, volume_level):
|
||||
if volume_level == 0:
|
||||
return VOLUME_ICONS["low"]
|
||||
elif volume_level <= 33:
|
||||
return VOLUME_ICONS["medium-low"]
|
||||
elif volume_level <= 66:
|
||||
return VOLUME_ICONS["medium-high"]
|
||||
else:
|
||||
return VOLUME_ICONS["high"]
|
||||
@@ -0,0 +1,19 @@
|
||||
import json
|
||||
|
||||
from fabric.hyprland.service import Hyprland
|
||||
from fabric.widgets.label import Label
|
||||
|
||||
connection = Hyprland()
|
||||
|
||||
workspaceData = connection.send_command("j/activeworkspace").reply
|
||||
activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"]
|
||||
workspace = Label(label=f"Workspace {activeWorkspace}")
|
||||
|
||||
|
||||
def on_workspace(obj, signal):
|
||||
global activeWorkspace
|
||||
activeWorkspace = json.loads(signal.data[0])
|
||||
workspace.set_label(f"Workspace {activeWorkspace}")
|
||||
|
||||
|
||||
connection.connect("event::workspace", on_workspace)
|
||||
Reference in new issue
Block a user